OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
LSL_Api.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Diagnostics;
32 using System.Drawing;
33 using System.Drawing.Imaging;
34 using System.Runtime.Remoting.Lifetime;
35 using System.Text;
36 using System.Threading;
37 using System.Text.RegularExpressions;
38 using System.Timers;
39 using Nini.Config;
40 using log4net;
41 using OpenMetaverse;
42 using OpenMetaverse.Assets;
43 using OpenMetaverse.StructuredData;
44 using OpenMetaverse.Packets;
45 using OpenMetaverse.Rendering;
46 using OpenSim;
47 using OpenSim.Framework;
48 
49 using OpenSim.Region.CoreModules;
50 using OpenSim.Region.CoreModules.World.Land;
51 using OpenSim.Region.CoreModules.World.Terrain;
52 using OpenSim.Region.Framework.Interfaces;
53 using OpenSim.Region.Framework.Scenes;
54 using OpenSim.Region.Framework.Scenes.Serialization;
56 using OpenSim.Region.Framework.Scenes.Scripting;
57 using OpenSim.Region.PhysicsModules.SharedBase;
58 using OpenSim.Region.ScriptEngine.Shared;
59 using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
60 using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
61 using OpenSim.Region.ScriptEngine.Interfaces;
62 using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
63 using OpenSim.Services.Interfaces;
69 
77 using System.Reflection;
79 using System.Linq;
81 
82 namespace OpenSim.Region.ScriptEngine.Shared.Api
83 {
84  // MUST be a ref type
85  public class UserInfoCacheEntry
86  {
87  public int time;
90  }
91 
95  public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
96  {
97  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
98 
99  public int LlRequestAgentDataCacheTimeoutMs { get; set; }
100 
103 
112 
113  protected bool throwErrorOnNotImplemented = false;
114  protected AsyncCommandManager AsyncCommands = null;
115  protected float m_ScriptDelayFactor = 1.0f;
116  protected float m_ScriptDistanceFactor = 1.0f;
117  protected float m_MinTimerInterval = 0.5f;
118  protected float m_recoilScaleFactor = 0.0f;
119 
120  protected DateTime m_timer = DateTime.Now;
121  protected bool m_waitingForScriptAnswer = false;
122  protected bool m_automaticLinkPermission = false;
123  protected IMessageTransferModule m_TransferModule = null;
124  protected int m_notecardLineReadCharsMax = 255;
125  protected int m_scriptConsoleChannel = 0;
126  protected bool m_scriptConsoleChannelEnabled = false;
127  protected bool m_debuggerSafe = false;
128  protected IUrlModule m_UrlModule = null;
129 
130  protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>();
131  protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
132  protected int m_sleepMsOnSetTexture = 200;
133  protected int m_sleepMsOnSetLinkTexture = 200;
134  protected int m_sleepMsOnScaleTexture = 200;
135  protected int m_sleepMsOnOffsetTexture = 200;
136  protected int m_sleepMsOnRotateTexture = 200;
137  protected int m_sleepMsOnSetPos = 200;
138  protected int m_sleepMsOnSetRot = 200;
139  protected int m_sleepMsOnSetLocalRot = 200;
140  protected int m_sleepMsOnPreloadSound = 1000;
141  protected int m_sleepMsOnMakeExplosion = 100;
142  protected int m_sleepMsOnMakeFountain = 100;
143  protected int m_sleepMsOnMakeSmoke = 100;
144  protected int m_sleepMsOnMakeFire = 100;
145  protected int m_sleepMsOnRezAtRoot = 100;
146  protected int m_sleepMsOnInstantMessage = 2000;
147  protected int m_sleepMsOnEmail = 20000;
148  protected int m_sleepMsOnCreateLink = 1000;
149  protected int m_sleepMsOnGiveInventory = 3000;
150  protected int m_sleepMsOnRequestAgentData = 100;
151  protected int m_sleepMsOnRequestInventoryData = 1000;
152  protected int m_sleepMsOnSetDamage = 5000;
153  protected int m_sleepMsOnTextBox = 1000;
154  protected int m_sleepMsOnAdjustSoundVolume = 100;
155  protected int m_sleepMsOnEjectFromLand = 5000;
156  protected int m_sleepMsOnAddToLandPassList = 100;
157  protected int m_sleepMsOnDialog = 1000;
158  protected int m_sleepMsOnRemoteLoadScript = 3000;
159  protected int m_sleepMsOnRemoteLoadScriptPin = 3000;
160  protected int m_sleepMsOnOpenRemoteDataChannel = 1000;
161  protected int m_sleepMsOnSendRemoteData = 3000;
162  protected int m_sleepMsOnRemoteDataReply = 3000;
163  protected int m_sleepMsOnCloseRemoteDataChannel = 1000;
164  protected int m_sleepMsOnSetPrimitiveParams = 200;
165  protected int m_sleepMsOnSetLinkPrimitiveParams = 200;
166  protected int m_sleepMsOnXorBase64Strings = 300;
167  protected int m_sleepMsOnSetParcelMusicURL = 2000;
168  protected int m_sleepMsOnGetPrimMediaParams = 1000;
169  protected int m_sleepMsOnGetLinkMedia = 1000;
170  protected int m_sleepMsOnSetPrimMediaParams = 1000;
171  protected int m_sleepMsOnSetLinkMedia = 1000;
172  protected int m_sleepMsOnClearPrimMedia = 1000;
173  protected int m_sleepMsOnClearLinkMedia = 1000;
174  protected int m_sleepMsOnRequestSimulatorData = 1000;
175  protected int m_sleepMsOnLoadURL = 10000;
176  protected int m_sleepMsOnParcelMediaCommandList = 2000;
177  protected int m_sleepMsOnParcelMediaQuery = 2000;
178  protected int m_sleepMsOnModPow = 1000;
179  protected int m_sleepMsOnSetPrimURL = 2000;
180  protected int m_sleepMsOnRefreshPrimURL = 20000;
181  protected int m_sleepMsOnMapDestination = 1000;
182  protected int m_sleepMsOnAddToLandBanList = 100;
183  protected int m_sleepMsOnRemoveFromLandPassList = 100;
184  protected int m_sleepMsOnRemoveFromLandBanList = 100;
185  protected int m_sleepMsOnResetLandBanList = 100;
186  protected int m_sleepMsOnResetLandPassList = 100;
187  protected int m_sleepMsOnGetParcelPrimOwners = 2000;
188  protected int m_sleepMsOnGetNumberOfNotecardLines = 100;
189  protected int m_sleepMsOnGetNotecardLine = 100;
190  protected string m_internalObjectHost = "lsl.opensim.local";
191  protected bool m_restrictEmail = false;
192  protected ISoundModule m_SoundModule = null;
193 
194  protected float m_avatarHeightCorrection = 0.2f;
195  protected bool m_useSimpleBoxesInGetBoundingBox = false;
196  protected bool m_addStatsInGetBoundingBox = false;
197 
198  //LSL Avatar Bounding Box (lABB), lower (1) and upper (2),
199  //standing (Std), Groundsitting (Grs), Sitting (Sit),
200  //along X, Y and Z axes, constants (0) and coefficients (1)
201  protected float m_lABB1StdX0 = -0.275f;
202  protected float m_lABB2StdX0 = 0.275f;
203  protected float m_lABB1StdY0 = -0.35f;
204  protected float m_lABB2StdY0 = 0.35f;
205  protected float m_lABB1StdZ0 = -0.1f;
206  protected float m_lABB1StdZ1 = -0.5f;
207  protected float m_lABB2StdZ0 = 0.1f;
208  protected float m_lABB2StdZ1 = 0.5f;
209  protected float m_lABB1GrsX0 = -0.3875f;
210  protected float m_lABB2GrsX0 = 0.3875f;
211  protected float m_lABB1GrsY0 = -0.5f;
212  protected float m_lABB2GrsY0 = 0.5f;
213  protected float m_lABB1GrsZ0 = -0.05f;
214  protected float m_lABB1GrsZ1 = -0.375f;
215  protected float m_lABB2GrsZ0 = 0.5f;
216  protected float m_lABB2GrsZ1 = 0.0f;
217  protected float m_lABB1SitX0 = -0.5875f;
218  protected float m_lABB2SitX0 = 0.1875f;
219  protected float m_lABB1SitY0 = -0.35f;
220  protected float m_lABB2SitY0 = 0.35f;
221  protected float m_lABB1SitZ0 = -0.35f;
222  protected float m_lABB1SitZ1 = -0.375f;
223  protected float m_lABB2SitZ0 = -0.25f;
224  protected float m_lABB2SitZ1 = 0.25f;
225 
226  protected float m_primSafetyCoeffX = 2.414214f;
227  protected float m_primSafetyCoeffY = 2.414214f;
228  protected float m_primSafetyCoeffZ = 1.618034f;
229  protected bool m_useCastRayV3 = false;
230  protected float m_floatToleranceInCastRay = 0.00001f;
231  protected float m_floatTolerance2InCastRay = 0.001f;
232  protected DetailLevel m_primLodInCastRay = DetailLevel.Medium;
233  protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium;
234  protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest;
235  protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium;
236  protected int m_maxHitsInCastRay = 16;
237  protected int m_maxHitsPerPrimInCastRay = 16;
238  protected int m_maxHitsPerObjectInCastRay = 16;
239  protected bool m_detectExitsInCastRay = false;
240  protected bool m_filterPartsInCastRay = false;
241  protected bool m_doAttachmentsInCastRay = false;
242  protected int m_msThrottleInCastRay = 200;
243  protected int m_msPerRegionInCastRay = 40;
244  protected int m_msPerAvatarInCastRay = 10;
245  protected int m_msMinInCastRay = 2;
246  protected int m_msMaxInCastRay = 40;
247  protected static List<CastRayCall> m_castRayCalls = new List<CastRayCall>();
248  protected bool m_useMeshCacheInCastRay = true;
249  protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>();
250 
251 // protected Timer m_ShoutSayTimer;
252  protected int m_SayShoutCount = 0;
253  DateTime m_lastSayShoutCheck;
254 
255  private Dictionary<string, string> MovementAnimationsForLSL =
256  new Dictionary<string, string> {
257  {"CROUCH", "Crouching"},
258  {"CROUCHWALK", "CrouchWalking"},
259  {"FALLDOWN", "Falling Down"},
260  {"FLY", "Flying"},
261  {"FLYSLOW", "FlyingSlow"},
262  {"HOVER", "Hovering"},
263  {"HOVER_UP", "Hovering Up"},
264  {"HOVER_DOWN", "Hovering Down"},
265  {"JUMP", "Jumping"},
266  {"LAND", "Landing"},
267  {"PREJUMP", "PreJumping"},
268  {"RUN", "Running"},
269  {"SIT","Sitting"},
270  {"SITGROUND","Sitting on Ground"},
271  {"STAND", "Standing"},
272  {"STANDUP", "Standing Up"},
273  {"STRIDE","Striding"},
274  {"SOFT_LAND", "Soft Landing"},
275  {"TURNLEFT", "Turning Left"},
276  {"TURNRIGHT", "Turning Right"},
277  {"WALK", "Walking"}
278  };
279 
280  //An array of HTTP/1.1 headers that are not allowed to be used
281  //as custom headers by llHTTPRequest.
282  private string[] HttpStandardHeaders =
283  {
284  "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language",
285  "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control",
286  "Connection", "Content-Encoding", "Content-Language",
287  "Content-Length", "Content-Location", "Content-MD5",
288  "Content-Range", "Content-Type", "Date", "ETag", "Expect",
289  "Expires", "From", "Host", "If-Match", "If-Modified-Since",
290  "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified",
291  "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate",
292  "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
293  "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent",
294  "Vary", "Via", "Warning", "WWW-Authenticate"
295  };
296 
297  public void Initialize(
298  IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
299  {
300  m_lastSayShoutCheck = DateTime.UtcNow;
301 
302  m_ScriptEngine = scriptEngine;
303  m_host = host;
304  m_item = item;
305  m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
306 
307  LoadConfig();
308 
309  m_TransferModule =
310  m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
311  m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
312  m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
313 
314  AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
315  }
316 
320  private void LoadConfig()
321  {
322  LlRequestAgentDataCacheTimeoutMs = 20000;
323 
324  IConfig seConfig = m_ScriptEngine.Config;
325 
326  if (seConfig != null)
327  {
328  m_ScriptDelayFactor =
329  seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor);
330  m_ScriptDistanceFactor =
331  seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor);
332  m_MinTimerInterval =
333  seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval);
334  m_automaticLinkPermission =
335  seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission);
336  m_notecardLineReadCharsMax =
337  seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax);
338 
339  // Rezzing an object with a velocity can create recoil. This feature seems to have been
340  // removed from recent versions of SL. The code computes recoil (vel*mass) and scales
341  // it by this factor. May be zero to turn off recoil all together.
342  m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
343  }
344 
345  if (m_notecardLineReadCharsMax > 65535)
346  m_notecardLineReadCharsMax = 65535;
347 
348  // load limits for particular subsystems.
349  IConfigSource seConfigSource = m_ScriptEngine.ConfigSource;
350 
351  if (seConfigSource != null)
352  {
353  IConfig lslConfig = seConfigSource.Configs["LL-Functions"];
354  if (lslConfig != null)
355  {
356  m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail);
357  m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection);
358  m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox);
359  m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox);
360  m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0);
361  m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0);
362  m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0);
363  m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0);
364  m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0);
365  m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1);
366  m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0);
367  m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1);
368  m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0);
369  m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0);
370  m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0);
371  m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0);
372  m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0);
373  m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1);
374  m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0);
375  m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1);
376  m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0);
377  m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0);
378  m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0);
379  m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0);
380  m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0);
381  m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1);
382  m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0);
383  m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1);
384  m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX);
385  m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY);
386  m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ);
387  m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3);
388  m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay);
389  m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay);
390  m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay);
391  m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay);
392  m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay);
393  m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay);
394  m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay);
395  m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
396  m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
397  m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
398  m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
399  m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
400  m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay);
401  m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay);
402  m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay);
403  m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay);
404  m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay);
405  m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay);
406  }
407 
408  IConfig smtpConfig = seConfigSource.Configs["SMTP"];
409  if (smtpConfig != null)
410  {
411  // there's an smtp config, so load in the snooze time.
412  EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
413 
414  m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
415  }
416  }
417  m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000;
418  }
419 
421  {
422  ILease lease = (ILease)base.InitializeLifetimeService();
423 
424  if (lease.CurrentState == LeaseState.Initial)
425  {
426  lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
427 // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
428 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
429  }
430  return lease;
431  }
432 
433  protected virtual void ScriptSleep(int delay)
434  {
435  delay = (int)((float)delay * m_ScriptDelayFactor);
436  if (delay == 0)
437  return;
438 
439  Sleep(delay);
440  }
441 
442  protected virtual void Sleep(int delay)
443  {
444  if (m_item == null) // Some unit tests don't set this
445  {
446  Thread.Sleep(delay);
447  return;
448  }
449 
450  m_ScriptEngine.SleepScript(m_item.ItemID, delay);
451  }
452 
457 
458  public Scene World
459  {
460  get { return m_ScriptEngine.World; }
461  }
462 
463  [DebuggerNonUserCode]
464  public void state(string newState)
465  {
466  m_ScriptEngine.SetState(m_item.ItemID, newState);
467  }
468 
473  [DebuggerNonUserCode]
474  public void llResetScript()
475  {
476  m_host.AddScriptLPS(1);
477 
478  // We need to tell the URL module, if we hav one, to release
479  // the allocated URLs
480  if (m_UrlModule != null)
481  m_UrlModule.ScriptRemoved(m_item.ItemID);
482 
483  m_ScriptEngine.ApiResetScript(m_item.ItemID);
484  }
485 
486  public void llResetOtherScript(string name)
487  {
488  UUID item;
489 
490  m_host.AddScriptLPS(1);
491 
492  if ((item = GetScriptByName(name)) != UUID.Zero)
493  m_ScriptEngine.ResetScript(item);
494  else
495  Error("llResetOtherScript", "Can't find script '" + name + "'");
496  }
497 
498  public LSL_Integer llGetScriptState(string name)
499  {
500  UUID item;
501 
502  m_host.AddScriptLPS(1);
503 
504  if ((item = GetScriptByName(name)) != UUID.Zero)
505  {
506  return m_ScriptEngine.GetScriptState(item) ?1:0;
507  }
508 
509  Error("llGetScriptState", "Can't find script '" + name + "'");
510 
511  // If we didn't find it, then it's safe to
512  // assume it is not running.
513 
514  return 0;
515  }
516 
517  public void llSetScriptState(string name, int run)
518  {
519  UUID item;
520 
521  m_host.AddScriptLPS(1);
522 
523  // These functions are supposed to be robust,
524  // so get the state one step at a time.
525 
526  if ((item = GetScriptByName(name)) != UUID.Zero)
527  {
528  m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
529  }
530  else
531  {
532  Error("llSetScriptState", "Can't find script '" + name + "'");
533  }
534  }
535 
536  public List<ScenePresence> GetLinkAvatars(int linkType)
537  {
538  List<ScenePresence> ret = new List<ScenePresence>();
539  if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
540  return ret;
541 
542  // List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
543  // this needs check
544  List<ScenePresence> avs = m_host.ParentGroup.GetSittingAvatars();
545  switch (linkType)
546  {
547  case ScriptBaseClass.LINK_SET:
548  return avs;
549 
550  case ScriptBaseClass.LINK_ROOT:
551  return ret;
552 
553  case ScriptBaseClass.LINK_ALL_OTHERS:
554  return avs;
555 
556  case ScriptBaseClass.LINK_ALL_CHILDREN:
557  return avs;
558 
559  case ScriptBaseClass.LINK_THIS:
560  return ret;
561 
562  default:
563  if (linkType < 0)
564  return ret;
565 
566  int partCount = m_host.ParentGroup.GetPartCount();
567 
568  if (linkType <= partCount)
569  {
570  return ret;
571  }
572  else
573  {
574  linkType = linkType - partCount;
575  if (linkType > avs.Count)
576  {
577  return ret;
578  }
579  else
580  {
581  ret.Add(avs[linkType-1]);
582  return ret;
583  }
584  }
585  }
586  }
587 
610  public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum)
611  {
612  if (linknum < 0)
613  {
614  if (linknum == ScriptBaseClass.LINK_THIS)
615  return part;
616  else
617  return null;
618  }
619 
620  int actualPrimCount = part.ParentGroup.PrimCount;
621  List<ScenePresence> sittingAvatars = part.ParentGroup.GetSittingAvatars();
622  int adjustedPrimCount = actualPrimCount + sittingAvatars.Count;
623 
624  // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
625  // prim that has any avatars sat upon it (in which case the root prim is link 1).
626  if (linknum == 0)
627  {
628  if (actualPrimCount == 1 && sittingAvatars.Count == 0)
629  return part;
630 
631  return null;
632  }
633  // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
634  // here we must match 1 (ScriptBaseClass.LINK_ROOT).
635  else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1)
636  {
637  if (sittingAvatars.Count > 0)
638  return part.ParentGroup.RootPart;
639  else
640  return null;
641  }
642  else if (linknum <= adjustedPrimCount)
643  {
644  if (linknum <= actualPrimCount)
645  {
646  return part.ParentGroup.GetLinkNumPart(linknum);
647  }
648  else
649  {
650  return sittingAvatars[linknum - actualPrimCount - 1];
651  }
652  }
653  else
654  {
655  return null;
656  }
657  }
658 
659  public List<SceneObjectPart> GetLinkParts(int linkType)
660  {
661  return GetLinkParts(m_host, linkType);
662  }
663 
664  public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
665  {
666  List<SceneObjectPart> ret = new List<SceneObjectPart>();
667  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
668  return ret;
669  ret.Add(part);
670 
671  switch (linkType)
672  {
673  case ScriptBaseClass.LINK_SET:
674  return new List<SceneObjectPart>(part.ParentGroup.Parts);
675 
676  case ScriptBaseClass.LINK_ROOT:
677  ret = new List<SceneObjectPart>();
678  ret.Add(part.ParentGroup.RootPart);
679  return ret;
680 
681  case ScriptBaseClass.LINK_ALL_OTHERS:
682  ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
683 
684  if (ret.Contains(part))
685  ret.Remove(part);
686 
687  return ret;
688 
689  case ScriptBaseClass.LINK_ALL_CHILDREN:
690  ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
691 
692  if (ret.Contains(part.ParentGroup.RootPart))
693  ret.Remove(part.ParentGroup.RootPart);
694  return ret;
695 
696  case ScriptBaseClass.LINK_THIS:
697  return ret;
698 
699  default:
700  if (linkType < 0)
701  return new List<SceneObjectPart>();
702 
703  SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
704  if (target == null)
705  return new List<SceneObjectPart>();
706  ret = new List<SceneObjectPart>();
707  ret.Add(target);
708  return ret;
709  }
710  }
711 
712  public List<ISceneEntity> GetLinkEntities(int linkType)
713  {
714  return GetLinkEntities(m_host, linkType);
715  }
716 
717  public List<ISceneEntity> GetLinkEntities(SceneObjectPart part, int linkType)
718  {
719  List<ISceneEntity> ret;
720 
721  switch (linkType)
722  {
723  case ScriptBaseClass.LINK_SET:
724  return new List<ISceneEntity>(part.ParentGroup.Parts);
725 
726  case ScriptBaseClass.LINK_ROOT:
727  return new List<ISceneEntity>() { part.ParentGroup.RootPart };
728 
729  case ScriptBaseClass.LINK_ALL_OTHERS:
730  ret = new List<ISceneEntity>(part.ParentGroup.Parts);
731 
732  if (ret.Contains(part))
733  ret.Remove(part);
734 
735  return ret;
736 
737  case ScriptBaseClass.LINK_ALL_CHILDREN:
738  ret = new List<ISceneEntity>(part.ParentGroup.Parts);
739 
740  if (ret.Contains(part.ParentGroup.RootPart))
741  ret.Remove(part.ParentGroup.RootPart);
742 
743  return ret;
744 
745  case ScriptBaseClass.LINK_THIS:
746  return new List<ISceneEntity>() { part };
747 
748  default:
749  if (linkType < 0)
750  return new List<ISceneEntity>();
751 
752  ISceneEntity target = GetLinkEntity(part, linkType);
753  if (target == null)
754  return new List<ISceneEntity>();
755 
756  return new List<ISceneEntity>() { target };
757  }
758  }
759 
760  //These are the implementations of the various ll-functions used by the LSL scripts.
761  public LSL_Float llSin(double f)
762  {
763  m_host.AddScriptLPS(1);
764  return (double)Math.Sin(f);
765  }
766 
767  public LSL_Float llCos(double f)
768  {
769  m_host.AddScriptLPS(1);
770  return (double)Math.Cos(f);
771  }
772 
773  public LSL_Float llTan(double f)
774  {
775  m_host.AddScriptLPS(1);
776  return (double)Math.Tan(f);
777  }
778 
779  public LSL_Float llAtan2(double x, double y)
780  {
781  m_host.AddScriptLPS(1);
782  return (double)Math.Atan2(x, y);
783  }
784 
785  public LSL_Float llSqrt(double f)
786  {
787  m_host.AddScriptLPS(1);
788  return (double)Math.Sqrt(f);
789  }
790 
791  public LSL_Float llPow(double fbase, double fexponent)
792  {
793  m_host.AddScriptLPS(1);
794  return (double)Math.Pow(fbase, fexponent);
795  }
796 
797  public LSL_Integer llAbs(int i)
798  {
799  // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
800  m_host.AddScriptLPS(1);
801  if (i == Int32.MinValue)
802  return i;
803  else
804  return (int)Math.Abs(i);
805  }
806 
807  public LSL_Float llFabs(double f)
808  {
809  m_host.AddScriptLPS(1);
810  return (double)Math.Abs(f);
811  }
812 
813  public LSL_Float llFrand(double mag)
814  {
815  m_host.AddScriptLPS(1);
816  lock (Util.RandomClass)
817  {
818  return Util.RandomClass.NextDouble() * mag;
819  }
820  }
821 
822  public LSL_Integer llFloor(double f)
823  {
824  m_host.AddScriptLPS(1);
825  return (int)Math.Floor(f);
826  }
827 
828  public LSL_Integer llCeil(double f)
829  {
830  m_host.AddScriptLPS(1);
831  return (int)Math.Ceiling(f);
832  }
833 
834  // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
835  public LSL_Integer llRound(double f)
836  {
837  m_host.AddScriptLPS(1);
838  return (int)Math.Round(f, MidpointRounding.AwayFromZero);
839  }
840 
841  //This next group are vector operations involving squaring and square root. ckrinke
843  {
844  m_host.AddScriptLPS(1);
845  return LSL_Vector.Mag(v);
846  }
847 
849  {
850  m_host.AddScriptLPS(1);
851  return LSL_Vector.Norm(v);
852  }
853 
854  private double VecDist(LSL_Vector a, LSL_Vector b)
855  {
856  double dx = a.x - b.x;
857  double dy = a.y - b.y;
858  double dz = a.z - b.z;
859  return Math.Sqrt(dx * dx + dy * dy + dz * dz);
860  }
861 
863  {
864  m_host.AddScriptLPS(1);
865  return VecDist(a, b);
866  }
867 
868  //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
869 
870  // Utility function for llRot2Euler
871 
873  {
874  m_host.AddScriptLPS(1);
875  LSL_Vector eul = new LSL_Vector();
876 
877  double sqw = q1.s*q1.s;
878  double sqx = q1.x*q1.x;
879  double sqy = q1.z*q1.z;
880  double sqz = q1.y*q1.y;
881  double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
882  double test = q1.x*q1.z + q1.y*q1.s;
883  if (test > 0.4999*unit) { // singularity at north pole
884  eul.z = 2 * Math.Atan2(q1.x,q1.s);
885  eul.y = Math.PI/2;
886  eul.x = 0;
887  return eul;
888  }
889  if (test < -0.4999*unit) { // singularity at south pole
890  eul.z = -2 * Math.Atan2(q1.x,q1.s);
891  eul.y = -Math.PI/2;
892  eul.x = 0;
893  return eul;
894  }
895  eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
896  eul.y = Math.Asin(2*test/unit);
897  eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
898  return eul;
899  }
900 
901  /* From wiki:
902  The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
903  in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
904  a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
905  vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
906  */
907 
908  /* How we arrived at this llEuler2Rot
909  *
910  * Experiment in SL to determine conventions:
911  * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
912  * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
913  * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
914  *
915  * Important facts about Quaternions
916  * - multiplication is non-commutative (a*b != b*a)
917  * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
918  *
919  * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
920  * Qx = c1+i*s1
921  * Qy = c2+j*s2;
922  * Qz = c3+k*s3;
923  *
924  * Rotations applied in order (from above) Z, Y, X
925  * Q = (Qz * Qy) * Qx
926  * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
927  * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
928  * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
929  * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
930  * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3
931  * regroup: x=i*(s1*c2*c3+c1*s2*s3)
932  * y=j*(c1*s2*c3-s1*c2*s3)
933  * z=k*(s1*s2*c3+c1*c2*s3)
934  * s= c1*c2*c3-s1*s2*s3
935  *
936  * This implementation agrees with the functions found here:
937  * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
938  * And with the results in SL.
939  *
940  * It's also possible to calculate llEuler2Rot by direct multiplication of
941  * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
942  * from the wiki).
943  * Apparently in some cases this is better from a numerical precision perspective?
944  */
945 
947  {
948  m_host.AddScriptLPS(1);
949 
950  double x,y,z,s;
951  v.x *= 0.5;
952  v.y *= 0.5;
953  v.z *= 0.5;
954  double c1 = Math.Cos(v.x);
955  double c2 = Math.Cos(v.y);
956  double c1c2 = c1 * c2;
957  double s1 = Math.Sin(v.x);
958  double s2 = Math.Sin(v.y);
959  double s1s2 = s1 * s2;
960  double c1s2 = c1 * s2;
961  double s1c2 = s1 * c2;
962  double c3 = Math.Cos(v.z);
963  double s3 = Math.Sin(v.z);
964 
965  x = s1c2 * c3 + c1s2 * s3;
966  y = c1s2 * c3 - s1c2 * s3;
967  z = s1s2 * c3 + c1c2 * s3;
968  s = c1c2 * c3 - s1s2 * s3;
969 
970  return new LSL_Rotation(x, y, z, s);
971  }
972 
974  {
975  m_host.AddScriptLPS(1);
976  double s;
977  double tr = fwd.x + left.y + up.z + 1.0;
978 
979  if (tr >= 1.0)
980  {
981  s = 0.5 / Math.Sqrt(tr);
982  return new LSL_Rotation(
983  (left.z - up.y) * s,
984  (up.x - fwd.z) * s,
985  (fwd.y - left.x) * s,
986  0.25 / s);
987  }
988  else
989  {
990  double max = (left.y > up.z) ? left.y : up.z;
991 
992  if (max < fwd.x)
993  {
994  s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
995  double x = s * 0.5;
996  s = 0.5 / s;
997  return new LSL_Rotation(
998  x,
999  (fwd.y + left.x) * s,
1000  (up.x + fwd.z) * s,
1001  (left.z - up.y) * s);
1002  }
1003  else if (max == left.y)
1004  {
1005  s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
1006  double y = s * 0.5;
1007  s = 0.5 / s;
1008  return new LSL_Rotation(
1009  (fwd.y + left.x) * s,
1010  y,
1011  (left.z + up.y) * s,
1012  (up.x - fwd.z) * s);
1013  }
1014  else
1015  {
1016  s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
1017  double z = s * 0.5;
1018  s = 0.5 / s;
1019  return new LSL_Rotation(
1020  (up.x + fwd.z) * s,
1021  (left.z + up.y) * s,
1022  z,
1023  (fwd.y - left.x) * s);
1024  }
1025  }
1026  }
1027 
1029  {
1030  m_host.AddScriptLPS(1);
1031 
1032  double x, y, z, m;
1033 
1034  m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
1035  // m is always greater than zero
1036  // if m is not equal to 1 then Rotation needs to be normalized
1037  if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
1038  {
1039  m = 1.0 / Math.Sqrt(m);
1040  r.x *= m;
1041  r.y *= m;
1042  r.z *= m;
1043  r.s *= m;
1044  }
1045 
1046  // Fast Algebric Calculations instead of Vectors & Quaternions Product
1047  x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
1048  y = 2 * (r.x * r.y + r.z * r.s);
1049  z = 2 * (r.x * r.z - r.y * r.s);
1050  return (new LSL_Vector(x, y, z));
1051  }
1052 
1054  {
1055  m_host.AddScriptLPS(1);
1056 
1057  double x, y, z, m;
1058 
1059  m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
1060  // m is always greater than zero
1061  // if m is not equal to 1 then Rotation needs to be normalized
1062  if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
1063  {
1064  m = 1.0 / Math.Sqrt(m);
1065  r.x *= m;
1066  r.y *= m;
1067  r.z *= m;
1068  r.s *= m;
1069  }
1070 
1071  // Fast Algebric Calculations instead of Vectors & Quaternions Product
1072  x = 2 * (r.x * r.y - r.z * r.s);
1073  y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
1074  z = 2 * (r.x * r.s + r.y * r.z);
1075  return (new LSL_Vector(x, y, z));
1076  }
1077 
1079  {
1080  m_host.AddScriptLPS(1);
1081  double x, y, z, m;
1082 
1083  m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
1084  // m is always greater than zero
1085  // if m is not equal to 1 then Rotation needs to be normalized
1086  if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
1087  {
1088  m = 1.0 / Math.Sqrt(m);
1089  r.x *= m;
1090  r.y *= m;
1091  r.z *= m;
1092  r.s *= m;
1093  }
1094 
1095  // Fast Algebric Calculations instead of Vectors & Quaternions Product
1096  x = 2 * (r.x * r.z + r.y * r.s);
1097  y = 2 * (-r.x * r.s + r.y * r.z);
1098  z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
1099  return (new LSL_Vector(x, y, z));
1100  }
1101 
1103  {
1104  //A and B should both be normalized
1105  m_host.AddScriptLPS(1);
1106  /* This method is more accurate than the SL one, and thus causes problems
1107  for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
1108 
1109  double dotProduct = LSL_Vector.Dot(a, b);
1110  LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
1111  double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
1112  double angle = Math.Acos(dotProduct / magProduct);
1113  LSL_Vector axis = LSL_Vector.Norm(crossProduct);
1114  double s = Math.Sin(angle / 2);
1115 
1116  double x = axis.x * s;
1117  double y = axis.y * s;
1118  double z = axis.z * s;
1119  double w = Math.Cos(angle / 2);
1120 
1121  if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
1122  return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1123 
1124  return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
1125  */
1126 
1127  // This method mimics the 180 errors found in SL
1128  // See www.euclideanspace.com... angleBetween
1129  LSL_Vector vec_a = a;
1130  LSL_Vector vec_b = b;
1131 
1132  // Eliminate zero length
1133  LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
1134  LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
1135  if (vec_a_mag < 0.00001 ||
1136  vec_b_mag < 0.00001)
1137  {
1138  return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1139  }
1140 
1141  // Normalize
1142  vec_a = llVecNorm(vec_a);
1143  vec_b = llVecNorm(vec_b);
1144 
1145  // Calculate axis and rotation angle
1146  LSL_Vector axis = vec_a % vec_b;
1147  LSL_Float cos_theta = vec_a * vec_b;
1148 
1149  // Check if parallel
1150  if (cos_theta > 0.99999)
1151  {
1152  return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1153  }
1154 
1155  // Check if anti-parallel
1156  else if (cos_theta < -0.99999)
1157  {
1158  LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
1159  if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
1160  return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
1161  }
1162  else // other rotation
1163  {
1164  LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
1165  axis = llVecNorm(axis);
1166  double x, y, z, s, t;
1167  s = Math.Cos(theta);
1168  t = Math.Sin(theta);
1169  x = axis.x * t;
1170  y = axis.y * t;
1171  z = axis.z * t;
1172  return new LSL_Rotation(x,y,z,s);
1173  }
1174  }
1175 
1176  public void llWhisper(int channelID, string text)
1177  {
1178  m_host.AddScriptLPS(1);
1179 
1180  if (text.Length > 1023)
1181  text = text.Substring(0, 1023);
1182 
1183  World.SimChat(Utils.StringToBytes(text),
1184  ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
1185 
1186  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1187  if (wComm != null)
1188  wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
1189  }
1190 
1191  private void CheckSayShoutTime()
1192  {
1193  DateTime now = DateTime.UtcNow;
1194  if ((now - m_lastSayShoutCheck).Ticks > 10000000) // 1sec
1195  {
1196  m_lastSayShoutCheck = now;
1197  m_SayShoutCount = 0;
1198  }
1199  else
1200  m_SayShoutCount++;
1201  }
1202 
1203  public void llSay(int channelID, string text)
1204  {
1205  m_host.AddScriptLPS(1);
1206 
1207  if (channelID == 0)
1208 // m_SayShoutCount++;
1209  CheckSayShoutTime();
1210 
1211  if (m_SayShoutCount >= 11)
1212  ScriptSleep(2000);
1213 
1214  if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
1215  {
1216  Console.WriteLine(text);
1217  }
1218  else
1219  {
1220  if (text.Length > 1023)
1221  text = text.Substring(0, 1023);
1222 
1223  World.SimChat(Utils.StringToBytes(text),
1224  ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
1225 
1226  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1227  if (wComm != null)
1228  wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
1229  }
1230  }
1231 
1232  public void llShout(int channelID, string text)
1233  {
1234  m_host.AddScriptLPS(1);
1235 
1236  if (channelID == 0)
1237 // m_SayShoutCount++;
1238  CheckSayShoutTime();
1239 
1240  if (m_SayShoutCount >= 11)
1241  ScriptSleep(2000);
1242 
1243  if (text.Length > 1023)
1244  text = text.Substring(0, 1023);
1245 
1246  World.SimChat(Utils.StringToBytes(text),
1247  ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
1248 
1249  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1250  if (wComm != null)
1251  wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
1252  }
1253 
1254  public void llRegionSay(int channelID, string text)
1255  {
1256  if (channelID == 0)
1257  {
1258  Error("llRegionSay", "Cannot use on channel 0");
1259  return;
1260  }
1261 
1262  if (text.Length > 1023)
1263  text = text.Substring(0, 1023);
1264 
1265  m_host.AddScriptLPS(1);
1266 
1267  // debug channel is also sent to avatars
1268  if (channelID == ScriptBaseClass.DEBUG_CHANNEL)
1269  {
1270  World.SimChat(Utils.StringToBytes(text),
1271  ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
1272 
1273  }
1274 
1275  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1276  if (wComm != null)
1277  wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
1278  }
1279 
1280  public void llRegionSayTo(string target, int channel, string msg)
1281  {
1282  if (msg.Length > 1023)
1283  msg = msg.Substring(0, 1023);
1284 
1285  m_host.AddScriptLPS(1);
1286 
1287  if (channel == ScriptBaseClass.DEBUG_CHANNEL)
1288  return;
1289 
1290  UUID TargetID;
1291  UUID.TryParse(target, out TargetID);
1292 
1293  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1294  if (wComm != null)
1295  wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg);
1296  }
1297 
1298  public LSL_Integer llListen(int channelID, string name, string ID, string msg)
1299  {
1300  m_host.AddScriptLPS(1);
1301  UUID keyID;
1302  UUID.TryParse(ID, out keyID);
1303  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1304  if (wComm != null)
1305  return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg);
1306  else
1307  return -1;
1308  }
1309 
1310  public void llListenControl(int number, int active)
1311  {
1312  m_host.AddScriptLPS(1);
1313  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1314  if (wComm != null)
1315  wComm.ListenControl(m_item.ItemID, number, active);
1316  }
1317 
1318  public void llListenRemove(int number)
1319  {
1320  m_host.AddScriptLPS(1);
1321  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1322  if (wComm != null)
1323  wComm.ListenRemove(m_item.ItemID, number);
1324  }
1325 
1326  public void llSensor(string name, string id, int type, double range, double arc)
1327  {
1328  m_host.AddScriptLPS(1);
1329  UUID keyID = UUID.Zero;
1330  UUID.TryParse(id, out keyID);
1331 
1332  AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host);
1333  }
1334 
1335  public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
1336  {
1337  m_host.AddScriptLPS(1);
1338  UUID keyID = UUID.Zero;
1339  UUID.TryParse(id, out keyID);
1340 
1341  AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host);
1342  }
1343 
1344  public void llSensorRemove()
1345  {
1346  m_host.AddScriptLPS(1);
1347  AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID);
1348  }
1349 
1350  public string resolveName(UUID objecUUID)
1351  {
1352  // try avatar username surname
1353  UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, objecUUID);
1354  if (account != null)
1355  {
1356  string avatarname = account.Name;
1357  return avatarname;
1358  }
1359  // try an scene object
1360  SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
1361  if (SOP != null)
1362  {
1363  string objectname = SOP.Name;
1364  return objectname;
1365  }
1366 
1367  EntityBase SensedObject;
1368  World.Entities.TryGetValue(objecUUID, out SensedObject);
1369 
1370  if (SensedObject == null)
1371  {
1372  IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
1373  if (groups != null)
1374  {
1375  GroupRecord gr = groups.GetGroupRecord(objecUUID);
1376  if (gr != null)
1377  return gr.GroupName;
1378  }
1379  return String.Empty;
1380  }
1381 
1382  return SensedObject.Name;
1383  }
1384 
1385  public LSL_String llDetectedName(int number)
1386  {
1387  m_host.AddScriptLPS(1);
1388  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1389  if (detectedParams == null)
1390  return String.Empty;
1391  return detectedParams.Name;
1392  }
1393 
1394  public LSL_String llDetectedKey(int number)
1395  {
1396  m_host.AddScriptLPS(1);
1397  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1398  if (detectedParams == null)
1399  return String.Empty;
1400  return detectedParams.Key.ToString();
1401  }
1402 
1403  public LSL_String llDetectedOwner(int number)
1404  {
1405  m_host.AddScriptLPS(1);
1406  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1407  if (detectedParams == null)
1408  return String.Empty;
1409  return detectedParams.Owner.ToString();
1410  }
1411 
1412  public LSL_Integer llDetectedType(int number)
1413  {
1414  m_host.AddScriptLPS(1);
1415  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1416  if (detectedParams == null)
1417  return 0;
1418  return new LSL_Integer(detectedParams.Type);
1419  }
1420 
1421  public LSL_Vector llDetectedPos(int number)
1422  {
1423  m_host.AddScriptLPS(1);
1424  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1425  if (detectedParams == null)
1426  return new LSL_Vector();
1427  return detectedParams.Position;
1428  }
1429 
1430  public LSL_Vector llDetectedVel(int number)
1431  {
1432  m_host.AddScriptLPS(1);
1433  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1434  if (detectedParams == null)
1435  return new LSL_Vector();
1436  return detectedParams.Velocity;
1437  }
1438 
1439  public LSL_Vector llDetectedGrab(int number)
1440  {
1441  m_host.AddScriptLPS(1);
1442  DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1443  if (parms == null)
1444  return new LSL_Vector(0, 0, 0);
1445 
1446  return parms.OffsetPos;
1447  }
1448 
1449  public LSL_Rotation llDetectedRot(int number)
1450  {
1451  m_host.AddScriptLPS(1);
1452  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1453  if (detectedParams == null)
1454  return new LSL_Rotation();
1455  return detectedParams.Rotation;
1456  }
1457 
1458  public LSL_Integer llDetectedGroup(int number)
1459  {
1460  m_host.AddScriptLPS(1);
1461  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1462  if (detectedParams == null)
1463  return new LSL_Integer(0);
1464  if (m_host.GroupID == detectedParams.Group)
1465  return new LSL_Integer(1);
1466  return new LSL_Integer(0);
1467  }
1468 
1470  {
1471  m_host.AddScriptLPS(1);
1472  DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1473  if (parms == null)
1474  return new LSL_Integer(0);
1475 
1476  return new LSL_Integer(parms.LinkNum);
1477  }
1478 
1483  {
1484  m_host.AddScriptLPS(1);
1485  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1486  if (detectedParams == null)
1487  return new LSL_Vector();
1488  return detectedParams.TouchBinormal;
1489  }
1490 
1495  {
1496  m_host.AddScriptLPS(1);
1497  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1498  if (detectedParams == null)
1499  return new LSL_Integer(-1);
1500  return new LSL_Integer(detectedParams.TouchFace);
1501  }
1502 
1507  {
1508  m_host.AddScriptLPS(1);
1509  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1510  if (detectedParams == null)
1511  return new LSL_Vector();
1512  return detectedParams.TouchNormal;
1513  }
1514 
1518  public LSL_Vector llDetectedTouchPos(int index)
1519  {
1520  m_host.AddScriptLPS(1);
1521  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1522  if (detectedParams == null)
1523  return new LSL_Vector();
1524  return detectedParams.TouchPos;
1525  }
1526 
1530  public LSL_Vector llDetectedTouchST(int index)
1531  {
1532  m_host.AddScriptLPS(1);
1533  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1534  if (detectedParams == null)
1535  return new LSL_Vector(-1.0, -1.0, 0.0);
1536  return detectedParams.TouchST;
1537  }
1538 
1542  public LSL_Vector llDetectedTouchUV(int index)
1543  {
1544  m_host.AddScriptLPS(1);
1545  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1546  if (detectedParams == null)
1547  return new LSL_Vector(-1.0, -1.0, 0.0);
1548  return detectedParams.TouchUV;
1549  }
1550 
1551  [DebuggerNonUserCode]
1552  public virtual void llDie()
1553  {
1554  m_host.AddScriptLPS(1);
1555  if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1556  }
1557 
1559  {
1560  m_host.AddScriptLPS(1);
1561  Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
1562 
1563  //Get the slope normal. This gives us the equation of the plane tangent to the slope.
1564  LSL_Vector vsn = llGroundNormal(offset);
1565 
1566  // Clamp to valid position
1567  if (pos.X < 0)
1568  pos.X = 0;
1569  else if (pos.X >= World.Heightmap.Width)
1570  pos.X = World.Heightmap.Width - 1;
1571  if (pos.Y < 0)
1572  pos.Y = 0;
1573  else if (pos.Y >= World.Heightmap.Height)
1574  pos.Y = World.Heightmap.Height - 1;
1575 
1576  //Get the height for the integer coordinates from the Heightmap
1577  float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y];
1578 
1579  //Calculate the difference between the actual coordinates and the integer coordinates
1580  float xdiff = pos.X - (float)((int)pos.X);
1581  float ydiff = pos.Y - (float)((int)pos.Y);
1582 
1583  //Use the equation of the tangent plane to adjust the height to account for slope
1584 
1585  return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight;
1586  }
1587 
1589  {
1590  m_host.AddScriptLPS(1);
1591  float cloudCover = 0f;
1592  ICloudModule module = World.RequestModuleInterface<ICloudModule>();
1593  if (module != null)
1594  {
1595  Vector3 pos = m_host.GetWorldPosition();
1596  int x = (int)(pos.X + offset.x);
1597  int y = (int)(pos.Y + offset.y);
1598 
1599  cloudCover = module.CloudCover(x, y, 0);
1600 
1601  }
1602  return cloudCover;
1603  }
1604 
1606  {
1607  m_host.AddScriptLPS(1);
1608  LSL_Vector wind = new LSL_Vector(0, 0, 0);
1609  IWindModule module = World.RequestModuleInterface<IWindModule>();
1610  if (module != null)
1611  {
1612  Vector3 pos = m_host.GetWorldPosition();
1613  int x = (int)(pos.X + offset.x);
1614  int y = (int)(pos.Y + offset.y);
1615 
1616  Vector3 windSpeed = module.WindSpeed(x, y, 0);
1617 
1618  wind.x = windSpeed.X;
1619  wind.y = windSpeed.Y;
1620  }
1621  return wind;
1622  }
1623 
1624  public void llSetStatus(int status, int value)
1625  {
1626  if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1627  return;
1628  m_host.AddScriptLPS(1);
1629 
1630  int statusrotationaxis = 0;
1631 
1632  if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
1633  {
1634  if (value != 0)
1635  {
1636  SceneObjectGroup group = m_host.ParentGroup;
1637  bool allow = true;
1638 
1639  int maxprims = World.m_linksetPhysCapacity;
1640  bool checkShape = (maxprims > 0 && group.PrimCount > maxprims);
1641 
1642  foreach (SceneObjectPart part in group.Parts)
1643  {
1644  if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
1645  {
1646  allow = false;
1647  break;
1648  }
1649  if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None)
1650  {
1651  if (--maxprims < 0)
1652  {
1653  allow = false;
1654  break;
1655  }
1656  }
1657  }
1658 
1659  if (!allow)
1660  return;
1661 
1662  if (m_host.ParentGroup.RootPart.PhysActor != null &&
1663  m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
1664  return;
1665 
1666  m_host.ScriptSetPhysicsStatus(true);
1667  }
1668  else
1669  {
1670  m_host.ScriptSetPhysicsStatus(false);
1671  }
1672  }
1673 
1674  if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
1675  {
1676  m_host.ParentGroup.ScriptSetPhantomStatus(value != 0);
1677  }
1678 
1679  if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
1680  {
1681  m_host.AddFlag(PrimFlags.CastShadows);
1682  }
1683 
1684  if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
1685  {
1686  statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
1687  }
1688 
1689  if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
1690  {
1691  statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
1692  }
1693 
1694  if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
1695  {
1696  statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
1697  }
1698 
1699  if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
1700  m_host.BlockGrab = value != 0;
1701 
1702  if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
1703  m_host.ParentGroup.BlockGrabOverride = value != 0;
1704 
1705  if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
1706  {
1707  if (value != 0)
1708  m_host.SetDieAtEdge(true);
1709  else
1710  m_host.SetDieAtEdge(false);
1711  }
1712 
1713  if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
1714  {
1715  if (value != 0)
1716  m_host.SetReturnAtEdge(true);
1717  else
1718  m_host.SetReturnAtEdge(false);
1719  }
1720 
1721  if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
1722  {
1723  if (value != 0)
1724  m_host.SetStatusSandbox(true);
1725  else
1726  m_host.SetStatusSandbox(false);
1727  }
1728 
1729  if (statusrotationaxis != 0)
1730  {
1731  m_host.SetAxisRotation(statusrotationaxis, value);
1732  }
1733  }
1734 
1735  private bool IsPhysical()
1736  {
1737  return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics);
1738  }
1739 
1740  public LSL_Integer llGetStatus(int status)
1741  {
1742  m_host.AddScriptLPS(1);
1743  // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
1744  switch (status)
1745  {
1746  case ScriptBaseClass.STATUS_PHYSICS:
1747  return IsPhysical() ? 1 : 0;
1748 
1749  case ScriptBaseClass.STATUS_PHANTOM:
1750  if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
1751  {
1752  return 1;
1753  }
1754  return 0;
1755 
1756  case ScriptBaseClass.STATUS_CAST_SHADOWS:
1757  if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
1758  {
1759  return 1;
1760  }
1761  return 0;
1762 
1763  case ScriptBaseClass.STATUS_BLOCK_GRAB:
1764  return m_host.BlockGrab ? 1 : 0;
1765 
1766  case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT:
1767  return m_host.ParentGroup.BlockGrabOverride ? 1 : 0;
1768 
1769  case ScriptBaseClass.STATUS_DIE_AT_EDGE:
1770  if (m_host.GetDieAtEdge())
1771  return 1;
1772  else
1773  return 0;
1774 
1775  case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
1776  if (m_host.GetReturnAtEdge())
1777  return 1;
1778  else
1779  return 0;
1780 
1781  case ScriptBaseClass.STATUS_ROTATE_X:
1782  // if (m_host.GetAxisRotation(2) != 0)
1783  if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
1784  return 1;
1785  else
1786  return 0;
1787 
1788  case ScriptBaseClass.STATUS_ROTATE_Y:
1789  if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
1790  return 1;
1791  else
1792  return 0;
1793 
1794  case ScriptBaseClass.STATUS_ROTATE_Z:
1795  if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
1796  return 1;
1797  else
1798  return 0;
1799 
1800  case ScriptBaseClass.STATUS_SANDBOX:
1801  if (m_host.GetStatusSandbox())
1802  return 1;
1803  else
1804  return 0;
1805  }
1806  return 0;
1807  }
1808 
1809  public void llSetScale(LSL_Vector scale)
1810  {
1811  m_host.AddScriptLPS(1);
1812  SetScale(m_host, scale);
1813  }
1814 
1815  protected void SetScale(SceneObjectPart part, LSL_Vector scale)
1816  {
1817  // TODO: this needs to trigger a persistance save as well
1818  if (part == null || part.ParentGroup.IsDeleted)
1819  return;
1820 
1821  // First we need to check whether or not we need to clamp the size of a physics-enabled prim
1822  PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
1823  if (pa != null && pa.IsPhysical)
1824  {
1825  scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x));
1826  scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
1827  scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
1828  }
1829  else
1830  {
1831  // If not physical, then we clamp the scale to the non-physical min/max
1832  scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
1833  scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
1834  scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
1835  }
1836 
1837  Vector3 tmp = part.Scale;
1838  tmp.X = (float)scale.x;
1839  tmp.Y = (float)scale.y;
1840  tmp.Z = (float)scale.z;
1841  part.Scale = tmp;
1843  }
1844 
1846  {
1847  m_host.AddScriptLPS(1);
1848  return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
1849  }
1850 
1851  public void llSetClickAction(int action)
1852  {
1853  m_host.AddScriptLPS(1);
1854  m_host.ClickAction = (byte)action;
1855  m_host.ParentGroup.HasGroupChanged = true;
1856  m_host.ScheduleFullUpdate();
1857  return;
1858  }
1859 
1860  public void llSetColor(LSL_Vector color, int face)
1861  {
1862  m_host.AddScriptLPS(1);
1863 
1864  SetColor(m_host, color, face);
1865  }
1866 
1867  protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1868  {
1869  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1870  return;
1871 
1872  Primitive.TextureEntry tex = part.Shape.Textures;
1873  Color4 texcolor;
1874  if (face >= 0 && face < GetNumberOfSides(part))
1875  {
1876  texcolor = tex.CreateFace((uint)face).RGBA;
1877  texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1878  texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1879  texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1880  tex.FaceTextures[face].RGBA = texcolor;
1881  part.UpdateTextureEntry(tex.GetBytes());
1882  return;
1883  }
1884  else if (face == ScriptBaseClass.ALL_SIDES)
1885  {
1886  for (uint i = 0; i < GetNumberOfSides(part); i++)
1887  {
1888  if (tex.FaceTextures[i] != null)
1889  {
1890  texcolor = tex.FaceTextures[i].RGBA;
1891  texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1892  texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1893  texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1894  tex.FaceTextures[i].RGBA = texcolor;
1895  }
1896  texcolor = tex.DefaultTexture.RGBA;
1897  texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1898  texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1899  texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1900  tex.DefaultTexture.RGBA = texcolor;
1901  }
1902  part.UpdateTextureEntry(tex.GetBytes());
1903  return;
1904  }
1905 
1906  if (face == ScriptBaseClass.ALL_SIDES)
1907  face = SceneObjectPart.ALL_SIDES;
1908 
1909  m_host.SetFaceColorAlpha(face, color, null);
1910  }
1911 
1912  public void llSetContentType(LSL_Key id, LSL_Integer type)
1913  {
1914  m_host.AddScriptLPS(1);
1915 
1916  if (m_UrlModule == null)
1917  return;
1918 
1919  // Make sure the content type is text/plain to start with
1920  m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1921 
1922  // Is the object owner online and in the region
1923  ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID);
1924  if (agent == null || agent.IsChildAgent)
1925  return; // Fail if the owner is not in the same region
1926 
1927  // Is it the embeded browser?
1928  string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent");
1929  if (userAgent.IndexOf("SecondLife") < 0)
1930  return; // Not the embedded browser. Is this check good enough?
1931 
1932  // Use the IP address of the client and check against the request
1933  // seperate logins from the same IP will allow all of them to get non-text/plain as long
1934  // as the owner is in the region. Same as SL!
1935  string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString();
1936  string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr");
1937  //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'");
1938  if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "")
1939  return;
1940  if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "")
1941  return;
1942 
1943  // If the request isnt from the same IP address then the request cannot be from the owner
1944  if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim()))
1945  return;
1946 
1947  switch (type)
1948  {
1949  case ScriptBaseClass.CONTENT_TYPE_HTML:
1950  m_UrlModule.HttpContentType(new UUID(id), "text/html");
1951  break;
1952  case ScriptBaseClass.CONTENT_TYPE_XML:
1953  m_UrlModule.HttpContentType(new UUID(id), "application/xml");
1954  break;
1955  case ScriptBaseClass.CONTENT_TYPE_XHTML:
1956  m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml");
1957  break;
1958  case ScriptBaseClass.CONTENT_TYPE_ATOM:
1959  m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml");
1960  break;
1961  case ScriptBaseClass.CONTENT_TYPE_JSON:
1962  m_UrlModule.HttpContentType(new UUID(id), "application/json");
1963  break;
1964  case ScriptBaseClass.CONTENT_TYPE_LLSD:
1965  m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml");
1966  break;
1967  case ScriptBaseClass.CONTENT_TYPE_FORM:
1968  m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded");
1969  break;
1970  case ScriptBaseClass.CONTENT_TYPE_RSS:
1971  m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml");
1972  break;
1973  default:
1974  m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1975  break;
1976  }
1977  }
1978 
1979 /*
1980  public void llSetContentType(LSL_Key id, LSL_Integer content_type)
1981  {
1982  if (m_UrlModule != null)
1983  {
1984  string type = "text.plain";
1985  if (content_type == (int)ScriptBaseClass.CONTENT_TYPE_HTML)
1986  type = "text/html";
1987 
1988  m_UrlModule.HttpContentType(new UUID(id),type);
1989  }
1990  }
1991 */
1992  public void SetTexGen(SceneObjectPart part, int face,int style)
1993  {
1994  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1995  return;
1996 
1997  Primitive.TextureEntry tex = part.Shape.Textures;
1998  MappingType textype;
1999  textype = MappingType.Default;
2000  if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR)
2001  textype = MappingType.Planar;
2002 
2003  if (face >= 0 && face < GetNumberOfSides(part))
2004  {
2005  tex.CreateFace((uint) face);
2006  tex.FaceTextures[face].TexMapType = textype;
2007  part.UpdateTextureEntry(tex.GetBytes());
2008  return;
2009  }
2010  else if (face == ScriptBaseClass.ALL_SIDES)
2011  {
2012  for (uint i = 0; i < GetNumberOfSides(part); i++)
2013  {
2014  if (tex.FaceTextures[i] != null)
2015  {
2016  tex.FaceTextures[i].TexMapType = textype;
2017  }
2018  tex.DefaultTexture.TexMapType = textype;
2019  }
2020  part.UpdateTextureEntry(tex.GetBytes());
2021  return;
2022  }
2023  }
2024 
2025  public void SetGlow(SceneObjectPart part, int face, float glow)
2026  {
2027  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2028  return;
2029 
2030  Primitive.TextureEntry tex = part.Shape.Textures;
2031  if (face >= 0 && face < GetNumberOfSides(part))
2032  {
2033  tex.CreateFace((uint) face);
2034  tex.FaceTextures[face].Glow = glow;
2035  part.UpdateTextureEntry(tex.GetBytes());
2036  return;
2037  }
2038  else if (face == ScriptBaseClass.ALL_SIDES)
2039  {
2040  for (uint i = 0; i < GetNumberOfSides(part); i++)
2041  {
2042  if (tex.FaceTextures[i] != null)
2043  {
2044  tex.FaceTextures[i].Glow = glow;
2045  }
2046  tex.DefaultTexture.Glow = glow;
2047  }
2048  part.UpdateTextureEntry(tex.GetBytes());
2049  return;
2050  }
2051  }
2052 
2053  public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
2054  {
2055  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2056  return;
2057 
2058  Shininess sval = new Shininess();
2059 
2060  switch (shiny)
2061  {
2062  case 0:
2063  sval = Shininess.None;
2064  break;
2065  case 1:
2066  sval = Shininess.Low;
2067  break;
2068  case 2:
2069  sval = Shininess.Medium;
2070  break;
2071  case 3:
2072  sval = Shininess.High;
2073  break;
2074  default:
2075  sval = Shininess.None;
2076  break;
2077  }
2078 
2079  Primitive.TextureEntry tex = part.Shape.Textures;
2080  if (face >= 0 && face < GetNumberOfSides(part))
2081  {
2082  tex.CreateFace((uint) face);
2083  tex.FaceTextures[face].Shiny = sval;
2084  tex.FaceTextures[face].Bump = bump;
2085  part.UpdateTextureEntry(tex.GetBytes());
2086  return;
2087  }
2088  else if (face == ScriptBaseClass.ALL_SIDES)
2089  {
2090  for (uint i = 0; i < GetNumberOfSides(part); i++)
2091  {
2092  if (tex.FaceTextures[i] != null)
2093  {
2094  tex.FaceTextures[i].Shiny = sval;
2095  tex.FaceTextures[i].Bump = bump;
2096  }
2097  tex.DefaultTexture.Shiny = sval;
2098  tex.DefaultTexture.Bump = bump;
2099  }
2100  part.UpdateTextureEntry(tex.GetBytes());
2101  return;
2102  }
2103  }
2104 
2105  public void SetFullBright(SceneObjectPart part, int face, bool bright)
2106  {
2107  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2108  return;
2109 
2110  Primitive.TextureEntry tex = part.Shape.Textures;
2111  if (face >= 0 && face < GetNumberOfSides(part))
2112  {
2113  tex.CreateFace((uint) face);
2114  tex.FaceTextures[face].Fullbright = bright;
2115  part.UpdateTextureEntry(tex.GetBytes());
2116  return;
2117  }
2118  else if (face == ScriptBaseClass.ALL_SIDES)
2119  {
2120  for (uint i = 0; i < GetNumberOfSides(part); i++)
2121  {
2122  if (tex.FaceTextures[i] != null)
2123  {
2124  tex.FaceTextures[i].Fullbright = bright;
2125  }
2126  }
2127  tex.DefaultTexture.Fullbright = bright;
2128  part.UpdateTextureEntry(tex.GetBytes());
2129  return;
2130  }
2131  }
2132 
2133  public LSL_Float llGetAlpha(int face)
2134  {
2135  m_host.AddScriptLPS(1);
2136 
2137  return GetAlpha(m_host, face);
2138  }
2139 
2140  protected LSL_Float GetAlpha(SceneObjectPart part, int face)
2141  {
2142  Primitive.TextureEntry tex = part.Shape.Textures;
2143  if (face == ScriptBaseClass.ALL_SIDES)
2144  {
2145  int i;
2146  double sum = 0.0;
2147  for (i = 0 ; i < GetNumberOfSides(part); i++)
2148  sum += (double)tex.GetFace((uint)i).RGBA.A;
2149  return sum;
2150  }
2151  if (face >= 0 && face < GetNumberOfSides(part))
2152  {
2153  return (double)tex.GetFace((uint)face).RGBA.A;
2154  }
2155  return 0.0;
2156  }
2157 
2158  public void llSetAlpha(double alpha, int face)
2159  {
2160  m_host.AddScriptLPS(1);
2161 
2162  SetAlpha(m_host, alpha, face);
2163  }
2164 
2165  public void llSetLinkAlpha(int linknumber, double alpha, int face)
2166  {
2167  m_host.AddScriptLPS(1);
2168 
2169  List<SceneObjectPart> parts = GetLinkParts(linknumber);
2170  if (parts.Count > 0)
2171  {
2172  try
2173  {
2174  foreach (SceneObjectPart part in parts)
2175  SetAlpha(part, alpha, face);
2176  }
2177  finally { }
2178  }
2179  }
2180 
2181  protected void SetAlpha(SceneObjectPart part, double alpha, int face)
2182  {
2183  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2184  return;
2185 
2186  Primitive.TextureEntry tex = part.Shape.Textures;
2187  Color4 texcolor;
2188  if (face >= 0 && face < GetNumberOfSides(part))
2189  {
2190  texcolor = tex.CreateFace((uint)face).RGBA;
2191  texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
2192  tex.FaceTextures[face].RGBA = texcolor;
2193  part.UpdateTextureEntry(tex.GetBytes());
2194  return;
2195  }
2196  else if (face == ScriptBaseClass.ALL_SIDES)
2197  {
2198  for (int i = 0; i < GetNumberOfSides(part); i++)
2199  {
2200  if (tex.FaceTextures[i] != null)
2201  {
2202  texcolor = tex.FaceTextures[i].RGBA;
2203  texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
2204  tex.FaceTextures[i].RGBA = texcolor;
2205  }
2206  }
2207 
2208  // In some cases, the default texture can be null, eg when every face
2209  // has a unique texture
2210  if (tex.DefaultTexture != null)
2211  {
2212  texcolor = tex.DefaultTexture.RGBA;
2213  texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
2214  tex.DefaultTexture.RGBA = texcolor;
2215  }
2216 
2217  part.UpdateTextureEntry(tex.GetBytes());
2218  return;
2219  }
2220  }
2221 
2235  protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
2236  float wind, float tension, LSL_Vector Force)
2237  {
2238  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2239  return;
2240 
2241  if (flexi)
2242  {
2243  part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
2244  // work once the prim is already flexi
2245  part.Shape.FlexiSoftness = softness;
2246  part.Shape.FlexiGravity = gravity;
2247  part.Shape.FlexiDrag = friction;
2248  part.Shape.FlexiWind = wind;
2249  part.Shape.FlexiTension = tension;
2250  part.Shape.FlexiForceX = (float)Force.x;
2251  part.Shape.FlexiForceY = (float)Force.y;
2252  part.Shape.FlexiForceZ = (float)Force.z;
2253  part.Shape.PathCurve = (byte)Extrusion.Flexible;
2254  }
2255  else
2256  {
2257  // Other values not set, they do not seem to be sent to the viewer
2258  // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off
2259  part.Shape.PathCurve = (byte)Extrusion.Straight;
2260  part.Shape.FlexiEntry = false;
2261  }
2262  part.ParentGroup.HasGroupChanged = true;
2263  part.ScheduleFullUpdate();
2264  }
2265 
2277  protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
2278  {
2279  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2280  return;
2281 
2282  if (light)
2283  {
2284  part.Shape.LightEntry = true;
2285  part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
2286  part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
2287  part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
2288  part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f);
2289  part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f);
2290  part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f);
2291  }
2292  else
2293  {
2294  part.Shape.LightEntry = false;
2295  }
2296 
2297  part.ParentGroup.HasGroupChanged = true;
2298  part.ScheduleFullUpdate();
2299  }
2300 
2301  public LSL_Vector llGetColor(int face)
2302  {
2303  m_host.AddScriptLPS(1);
2304  return GetColor(m_host, face);
2305  }
2306 
2307  protected LSL_Vector GetColor(SceneObjectPart part, int face)
2308  {
2309  Primitive.TextureEntry tex = part.Shape.Textures;
2310  Color4 texcolor;
2311  LSL_Vector rgb = new LSL_Vector();
2312  int nsides = GetNumberOfSides(part);
2313 
2314  if (face == ScriptBaseClass.ALL_SIDES)
2315  {
2316  int i;
2317  for (i = 0; i < nsides; i++)
2318  {
2319  texcolor = tex.GetFace((uint)i).RGBA;
2320  rgb.x += texcolor.R;
2321  rgb.y += texcolor.G;
2322  rgb.z += texcolor.B;
2323  }
2324 
2325  float invnsides = 1.0f / (float)nsides;
2326 
2327  rgb.x *= invnsides;
2328  rgb.y *= invnsides;
2329  rgb.z *= invnsides;
2330 
2331  return rgb;
2332  }
2333  if (face >= 0 && face < nsides)
2334  {
2335  texcolor = tex.GetFace((uint)face).RGBA;
2336  rgb.x = texcolor.R;
2337  rgb.y = texcolor.G;
2338  rgb.z = texcolor.B;
2339 
2340  return rgb;
2341  }
2342  else
2343  {
2344  return new LSL_Vector();
2345  }
2346  }
2347 
2348  public void llSetTexture(string texture, int face)
2349  {
2350  m_host.AddScriptLPS(1);
2351  SetTexture(m_host, texture, face);
2352  ScriptSleep(m_sleepMsOnSetTexture);
2353  }
2354 
2355  public void llSetLinkTexture(int linknumber, string texture, int face)
2356  {
2357  m_host.AddScriptLPS(1);
2358 
2359  List<SceneObjectPart> parts = GetLinkParts(linknumber);
2360  if (parts.Count > 0)
2361  {
2362  try
2363  {
2364  foreach (SceneObjectPart part in parts)
2365  SetTexture(part, texture, face);
2366  }
2367  finally { }
2368  }
2369  ScriptSleep(m_sleepMsOnSetLinkTexture);
2370  }
2371 
2372  protected void SetTexture(SceneObjectPart part, string texture, int face)
2373  {
2374  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2375  return;
2376 
2377  UUID textureID = new UUID();
2378 
2379  textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
2380  if (textureID == UUID.Zero)
2381  {
2382  if (!UUID.TryParse(texture, out textureID))
2383  return;
2384  }
2385 
2386  Primitive.TextureEntry tex = part.Shape.Textures;
2387 
2388  if (face >= 0 && face < GetNumberOfSides(part))
2389  {
2390  Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2391  texface.TextureID = textureID;
2392  tex.FaceTextures[face] = texface;
2393  part.UpdateTextureEntry(tex.GetBytes());
2394  return;
2395  }
2396  else if (face == ScriptBaseClass.ALL_SIDES)
2397  {
2398  for (uint i = 0; i < GetNumberOfSides(part); i++)
2399  {
2400  if (tex.FaceTextures[i] != null)
2401  {
2402  tex.FaceTextures[i].TextureID = textureID;
2403  }
2404  }
2405  tex.DefaultTexture.TextureID = textureID;
2406  part.UpdateTextureEntry(tex.GetBytes());
2407  return;
2408  }
2409  }
2410 
2411  public void llScaleTexture(double u, double v, int face)
2412  {
2413  m_host.AddScriptLPS(1);
2414 
2415  ScaleTexture(m_host, u, v, face);
2416  ScriptSleep(m_sleepMsOnScaleTexture);
2417  }
2418 
2419  protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
2420  {
2421  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2422  return;
2423 
2424  Primitive.TextureEntry tex = part.Shape.Textures;
2425  if (face >= 0 && face < GetNumberOfSides(part))
2426  {
2427  Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2428  texface.RepeatU = (float)u;
2429  texface.RepeatV = (float)v;
2430  tex.FaceTextures[face] = texface;
2431  part.UpdateTextureEntry(tex.GetBytes());
2432  return;
2433  }
2434  if (face == ScriptBaseClass.ALL_SIDES)
2435  {
2436  for (int i = 0; i < GetNumberOfSides(part); i++)
2437  {
2438  if (tex.FaceTextures[i] != null)
2439  {
2440  tex.FaceTextures[i].RepeatU = (float)u;
2441  tex.FaceTextures[i].RepeatV = (float)v;
2442  }
2443  }
2444  tex.DefaultTexture.RepeatU = (float)u;
2445  tex.DefaultTexture.RepeatV = (float)v;
2446  part.UpdateTextureEntry(tex.GetBytes());
2447  return;
2448  }
2449  }
2450 
2451  public void llOffsetTexture(double u, double v, int face)
2452  {
2453  m_host.AddScriptLPS(1);
2454  OffsetTexture(m_host, u, v, face);
2455  ScriptSleep(m_sleepMsOnOffsetTexture);
2456  }
2457 
2458  protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
2459  {
2460  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2461  return;
2462 
2463  Primitive.TextureEntry tex = part.Shape.Textures;
2464  if (face >= 0 && face < GetNumberOfSides(part))
2465  {
2466  Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2467  texface.OffsetU = (float)u;
2468  texface.OffsetV = (float)v;
2469  tex.FaceTextures[face] = texface;
2470  part.UpdateTextureEntry(tex.GetBytes());
2471  return;
2472  }
2473  if (face == ScriptBaseClass.ALL_SIDES)
2474  {
2475  for (int i = 0; i < GetNumberOfSides(part); i++)
2476  {
2477  if (tex.FaceTextures[i] != null)
2478  {
2479  tex.FaceTextures[i].OffsetU = (float)u;
2480  tex.FaceTextures[i].OffsetV = (float)v;
2481  }
2482  }
2483  tex.DefaultTexture.OffsetU = (float)u;
2484  tex.DefaultTexture.OffsetV = (float)v;
2485  part.UpdateTextureEntry(tex.GetBytes());
2486  return;
2487  }
2488  }
2489 
2490  public void llRotateTexture(double rotation, int face)
2491  {
2492  m_host.AddScriptLPS(1);
2493  RotateTexture(m_host, rotation, face);
2494  ScriptSleep(m_sleepMsOnRotateTexture);
2495  }
2496 
2497  protected void RotateTexture(SceneObjectPart part, double rotation, int face)
2498  {
2499  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2500  return;
2501 
2502  Primitive.TextureEntry tex = part.Shape.Textures;
2503  if (face >= 0 && face < GetNumberOfSides(part))
2504  {
2505  Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2506  texface.Rotation = (float)rotation;
2507  tex.FaceTextures[face] = texface;
2508  part.UpdateTextureEntry(tex.GetBytes());
2509  return;
2510  }
2511  if (face == ScriptBaseClass.ALL_SIDES)
2512  {
2513  for (int i = 0; i < GetNumberOfSides(part); i++)
2514  {
2515  if (tex.FaceTextures[i] != null)
2516  {
2517  tex.FaceTextures[i].Rotation = (float)rotation;
2518  }
2519  }
2520  tex.DefaultTexture.Rotation = (float)rotation;
2521  part.UpdateTextureEntry(tex.GetBytes());
2522  return;
2523  }
2524  }
2525 
2526  public LSL_String llGetTexture(int face)
2527  {
2528  m_host.AddScriptLPS(1);
2529  return GetTexture(m_host, face);
2530  }
2531 
2532  protected LSL_String GetTexture(SceneObjectPart part, int face)
2533  {
2534  Primitive.TextureEntry tex = part.Shape.Textures;
2535  if (face == ScriptBaseClass.ALL_SIDES)
2536  {
2537  face = 0;
2538  }
2539 
2540  if (face >= 0 && face < GetNumberOfSides(part))
2541  {
2542  Primitive.TextureEntryFace texface;
2543  texface = tex.GetFace((uint)face);
2544  string texture = texface.TextureID.ToString();
2545 
2546  lock (part.TaskInventory)
2547  {
2548  foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory)
2549  {
2550  if (inv.Value.AssetID == texface.TextureID)
2551  {
2552  texture = inv.Value.Name.ToString();
2553  break;
2554  }
2555  }
2556  }
2557 
2558  return texture;
2559  }
2560  else
2561  {
2562  return UUID.Zero.ToString();
2563  }
2564  }
2565 
2566  public void llSetPos(LSL_Vector pos)
2567  {
2568  m_host.AddScriptLPS(1);
2569 
2570  SetPos(m_host, pos, true);
2571 
2572  ScriptSleep(m_sleepMsOnSetPos);
2573  }
2574 
2583  {
2584  m_host.AddScriptLPS(1);
2585 
2586  // BEGIN WORKAROUND
2587  // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
2588  //
2589  // This workaround is to prevent silent failure of this function.
2590  // According to the specification on the SL Wiki, providing a position outside of the
2591  if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
2592  {
2593  return 0;
2594  }
2595  // END WORK AROUND
2596  else if ( // this is not part of the workaround if-block because it's not related to the workaround.
2597  IsPhysical() ||
2598  m_host.ParentGroup.IsAttachment || // return FALSE if attachment
2599  (
2600  pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
2601  pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2602  pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2603  pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2604  pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
2605  )
2606  )
2607  {
2608  return 0;
2609  }
2610 
2611  // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range.
2612  // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
2613 
2614  Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
2615  LandData here = World.GetLandData(objectPos);
2616  LandData there = World.GetLandData(pos);
2617 
2618  // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
2619 
2620  bool sameParcel = here.GlobalID == there.GlobalID;
2621 
2622  if (!sameParcel && !World.Permissions.CanRezObject(
2623  m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos))
2624  {
2625  return 0;
2626  }
2627 
2628  SetPos(m_host.ParentGroup.RootPart, pos, false);
2629 
2630  return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0;
2631  }
2632 
2633  // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2634  // note linked setpos is capped "differently"
2635  private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
2636  {
2637  if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor)
2638  return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start);
2639  else
2640  return end;
2641  }
2642 
2643  protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos, bool adjust)
2644  {
2645  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2646  return fromPos;
2647 
2648  // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2649 
2650 
2651  float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2652  bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
2653 
2654  if (part.ParentGroup.RootPart == part)
2655  {
2656  if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2657  targetPos.z = ground;
2658  }
2659  if (adjust)
2660  return SetPosAdjust(fromPos, targetPos);
2661 
2662  return targetPos;
2663  }
2664 
2671  protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2672  {
2673  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2674  return;
2675 
2676  LSL_Vector currentPos = GetPartLocalPos(part);
2677  LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos, adjust);
2678 
2679 
2680  if (part.ParentGroup.RootPart == part)
2681  {
2682  SceneObjectGroup parent = part.ParentGroup;
2683  if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos))
2684  return;
2685  parent.UpdateGroupPosition((Vector3)toPos);
2686  }
2687  else
2688  {
2689  part.OffsetPosition = (Vector3)toPos;
2690 // SceneObjectGroup parent = part.ParentGroup;
2691 // parent.HasGroupChanged = true;
2692 // parent.ScheduleGroupForTerseUpdate();
2693  part.ScheduleTerseUpdate();
2694  }
2695  }
2696 
2698  {
2699  m_host.AddScriptLPS(1);
2700  return m_host.GetWorldPosition();
2701  }
2702 
2704  {
2705  m_host.AddScriptLPS(1);
2706  return GetPartLocalPos(m_host);
2707  }
2708 
2710  {
2711  m_host.AddScriptLPS(1);
2712 
2713  Vector3 pos;
2714 
2715  if (!part.IsRoot)
2716  {
2717  pos = part.OffsetPosition;
2718  }
2719  else
2720  {
2721  if (part.ParentGroup.IsAttachment)
2722  pos = part.AttachedPos;
2723  else
2724  pos = part.AbsolutePosition;
2725  }
2726 
2727 // m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2728 
2729  return new LSL_Vector(pos);
2730  }
2731 
2732  public void llSetRot(LSL_Rotation rot)
2733  {
2734  m_host.AddScriptLPS(1);
2735 
2736  // try to let this work as in SL...
2737  if (m_host.ParentID == 0 || (m_host.ParentGroup != null && m_host == m_host.ParentGroup.RootPart))
2738  {
2739  // special case: If we are root, rotate complete SOG to new rotation
2740  SetRot(m_host, rot);
2741  }
2742  else
2743  {
2744  // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
2745  SceneObjectPart rootPart = m_host.ParentGroup.RootPart;
2746  if (rootPart != null) // better safe than sorry
2747  {
2748  SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
2749  }
2750  }
2751 
2752  ScriptSleep(m_sleepMsOnSetRot);
2753  }
2754 
2755  public void llSetLocalRot(LSL_Rotation rot)
2756  {
2757  m_host.AddScriptLPS(1);
2758  SetRot(m_host, rot);
2759  ScriptSleep(m_sleepMsOnSetLocalRot);
2760  }
2761 
2762  protected void SetRot(SceneObjectPart part, Quaternion rot)
2763  {
2764  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2765  return;
2766 
2767  bool isroot = (part == part.ParentGroup.RootPart);
2768  bool isphys;
2769 
2770  PhysicsActor pa = part.PhysActor;
2771 
2772  // keep using physactor ideia of isphysical
2773  // it should be SOP ideia of that
2774  // not much of a issue with ubOde
2775  if (pa != null && pa.IsPhysical)
2776  isphys = true;
2777  else
2778  isphys = false;
2779 
2780  // SL doesn't let scripts rotate root of physical linksets
2781  if (isroot && isphys)
2782  return;
2783 
2784  part.UpdateRotation(rot);
2785 
2786  // Update rotation does not move the object in the physics engine if it's a non physical linkset
2787  // so do a nasty update of parts positions if is a root part rotation
2788  if (isroot && pa != null) // with if above implies non physical root part
2789  {
2790  part.ParentGroup.ResetChildPrimPhysicsPositions();
2791  }
2792  else // fix sitting avatars. This is only needed bc of how we link avas to child parts, not root part
2793  {
2794  // List<ScenePresence> sittingavas = part.ParentGroup.GetLinkedAvatars();
2795  List<ScenePresence> sittingavas = part.ParentGroup.GetSittingAvatars();
2796  if (sittingavas.Count > 0)
2797  {
2798  foreach (ScenePresence av in sittingavas)
2799  {
2800  if (isroot || part.LocalId == av.ParentID)
2801  av.SendTerseUpdateToAllClients();
2802  }
2803  }
2804  }
2805  }
2806 
2811  {
2812  // unlinked or root prim then use llRootRotation
2813  // see llRootRotaion for references.
2814  if (m_host.LinkNum == 0 || m_host.LinkNum == 1)
2815  {
2816  return llGetRootRotation();
2817  }
2818 
2819  m_host.AddScriptLPS(1);
2820  Quaternion q = m_host.GetWorldRotation();
2821 
2822  if (m_host.ParentGroup != null && m_host.ParentGroup.AttachmentPoint != 0)
2823  {
2824  ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2825  if (avatar != null)
2826  {
2827  if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2828  q = avatar.CameraRotation * q; // Mouselook
2829  else
2830  q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2831  }
2832  }
2833 
2834  return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2835  }
2836 
2837  private LSL_Rotation GetPartRot(SceneObjectPart part)
2838  {
2839  Quaternion q;
2840  if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim
2841  {
2842  if (part.ParentGroup.AttachmentPoint != 0)
2843  {
2844  ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
2845  if (avatar != null)
2846  {
2847  if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2848  q = avatar.CameraRotation; // Mouselook
2849  else
2850  q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate
2851  }
2852  else
2853  q = part.ParentGroup.GroupRotation; // Likely never get here but just in case
2854  }
2855  else
2856  q = part.ParentGroup.GroupRotation; // just the group rotation
2857 
2858  return new LSL_Rotation(q);
2859  }
2860 
2861  q = part.GetWorldRotation();
2862  if (part.ParentGroup.AttachmentPoint != 0)
2863  {
2864  ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
2865  if (avatar != null)
2866  {
2867  if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2868  q = avatar.CameraRotation * q; // Mouselook
2869  else
2870  q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2871  }
2872  }
2873 
2874  return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2875  }
2876 
2878  {
2879  return GetPartLocalRot(m_host);
2880  }
2881 
2882  private LSL_Rotation GetPartLocalRot(SceneObjectPart part)
2883  {
2884  m_host.AddScriptLPS(1);
2885  Quaternion rot = part.RotationOffset;
2886  return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
2887  }
2888 
2889  public void llSetForce(LSL_Vector force, int local)
2890  {
2891  m_host.AddScriptLPS(1);
2892 
2893  if (!m_host.ParentGroup.IsDeleted)
2894  {
2895  if (local != 0)
2896  force *= llGetRot();
2897 
2898  m_host.ParentGroup.RootPart.SetForce(force);
2899  }
2900  }
2901 
2903  {
2904  LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
2905 
2906  m_host.AddScriptLPS(1);
2907 
2908  if (!m_host.ParentGroup.IsDeleted)
2909  {
2910  force = m_host.ParentGroup.RootPart.GetForce();
2911  }
2912 
2913  return force;
2914  }
2915 
2916  public void llSetVelocity(LSL_Vector vel, int local)
2917  {
2918  m_host.AddScriptLPS(1);
2919  m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0);
2920  }
2921 
2922  public void llSetAngularVelocity(LSL_Vector avel, int local)
2923  {
2924  m_host.AddScriptLPS(1);
2925  m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0);
2926  }
2927  public LSL_Integer llTarget(LSL_Vector position, double range)
2928  {
2929  m_host.AddScriptLPS(1);
2930  return m_host.ParentGroup.registerTargetWaypoint(position,
2931  (float)range);
2932  }
2933 
2934  public void llTargetRemove(int number)
2935  {
2936  m_host.AddScriptLPS(1);
2937  m_host.ParentGroup.unregisterTargetWaypoint(number);
2938  }
2939 
2940  public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
2941  {
2942  m_host.AddScriptLPS(1);
2943  return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error);
2944  }
2945 
2946  public void llRotTargetRemove(int number)
2947  {
2948  m_host.AddScriptLPS(1);
2949  m_host.ParentGroup.unregisterRotTargetWaypoint(number);
2950  }
2951 
2952  public void llMoveToTarget(LSL_Vector target, double tau)
2953  {
2954  m_host.AddScriptLPS(1);
2955  m_host.MoveToTarget(target, (float)tau);
2956  }
2957 
2958  public void llStopMoveToTarget()
2959  {
2960  m_host.AddScriptLPS(1);
2961  m_host.StopMoveToTarget();
2962  }
2963 
2964  public void llApplyImpulse(LSL_Vector force, int local)
2965  {
2966  m_host.AddScriptLPS(1);
2967  //No energy force yet
2968  Vector3 v = force;
2969  if (v.Length() > 20000.0f)
2970  {
2971  v.Normalize();
2972  v = v * 20000.0f;
2973  }
2974  m_host.ApplyImpulse(v, local != 0);
2975  }
2976 
2977 
2978  public void llApplyRotationalImpulse(LSL_Vector force, int local)
2979  {
2980  m_host.AddScriptLPS(1);
2981  m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2982  }
2983 
2984  public void llSetTorque(LSL_Vector torque, int local)
2985  {
2986  m_host.AddScriptLPS(1);
2987  m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2988  }
2989 
2991  {
2992  m_host.AddScriptLPS(1);
2993 
2994  return new LSL_Vector(m_host.ParentGroup.GetTorque());
2995  }
2996 
2997  public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
2998  {
2999  m_host.AddScriptLPS(1);
3000  llSetForce(force, local);
3001  llSetTorque(torque, local);
3002  }
3003 
3004 
3006  {
3007  m_host.AddScriptLPS(1);
3008 
3009  Vector3 vel = Vector3.Zero;
3010 
3011  if (m_host.ParentGroup.IsAttachment)
3012  {
3013  ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
3014  if (avatar != null)
3015  vel = avatar.GetWorldVelocity();
3016  }
3017  else
3018  {
3019  vel = m_host.ParentGroup.RootPart.Velocity;
3020  }
3021 
3022  return new LSL_Vector(vel);
3023  }
3024 
3026  {
3027  m_host.AddScriptLPS(1);
3028 
3029  return new LSL_Vector(m_host.Acceleration);
3030  }
3031 
3033  {
3034  m_host.AddScriptLPS(1);
3035  Vector3 avel = m_host.AngularVelocity;
3036  return new LSL_Vector(avel.X, avel.Y, avel.Z);
3037  }
3038 
3040  {
3041  m_host.AddScriptLPS(1);
3042  return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4));
3043  }
3044 
3046  {
3047  m_host.AddScriptLPS(1);
3048  return DateTime.Now.TimeOfDay.TotalSeconds;
3049  }
3050 
3052  {
3053  m_host.AddScriptLPS(1);
3054  TimeSpan ScriptTime = DateTime.Now - m_timer;
3055  return (double)(ScriptTime.TotalMilliseconds / 1000);
3056  }
3057 
3058  public void llResetTime()
3059  {
3060  m_host.AddScriptLPS(1);
3061  m_timer = DateTime.Now;
3062  }
3063 
3065  {
3066  m_host.AddScriptLPS(1);
3067  TimeSpan ScriptTime = DateTime.Now - m_timer;
3068  m_timer = DateTime.Now;
3069  return (double)(ScriptTime.TotalMilliseconds / 1000);
3070  }
3071 
3072  public void llSound(string sound, double volume, int queue, int loop)
3073  {
3074  m_host.AddScriptLPS(1);
3075  Deprecated("llSound", "Use llPlaySound instead");
3076  }
3077 
3078  // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
3079  // 20080530 Updated to remove code duplication
3080  public void llPlaySound(string sound, double volume)
3081  {
3082  m_host.AddScriptLPS(1);
3083 
3084  // send the sound, once, to all clients in range
3085  if (m_SoundModule != null)
3086  {
3087  m_SoundModule.SendSound(
3088  m_host.UUID,
3089  ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
3090  volume, false, 0,
3091  0, false, false);
3092  }
3093  }
3094 
3095  public void llLoopSound(string sound, double volume)
3096  {
3097  m_host.AddScriptLPS(1);
3098  if (m_SoundModule != null)
3099  {
3100  m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
3101  volume, 20, false,false);
3102  }
3103  }
3104 
3105  public void llLoopSoundMaster(string sound, double volume)
3106  {
3107  m_host.AddScriptLPS(1);
3108  if (m_SoundModule != null)
3109  {
3110  m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
3111  volume, 20, true, false);
3112  }
3113  }
3114 
3115  public void llLoopSoundSlave(string sound, double volume)
3116  {
3117  m_host.AddScriptLPS(1);
3118  if (m_SoundModule != null)
3119  {
3120  m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
3121  volume, 20, false, true);
3122  }
3123  }
3124 
3125  public void llPlaySoundSlave(string sound, double volume)
3126  {
3127  m_host.AddScriptLPS(1);
3128 
3129  // send the sound, once, to all clients in range
3130  if (m_SoundModule != null)
3131  {
3132  m_SoundModule.SendSound(m_host.UUID,
3133  ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
3134  0, true, false);
3135  }
3136  }
3137 
3138  public void llTriggerSound(string sound, double volume)
3139  {
3140  m_host.AddScriptLPS(1);
3141  // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
3142  if (m_SoundModule != null)
3143  {
3144  m_SoundModule.SendSound(m_host.UUID,
3145  ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0,
3146  false, false);
3147  }
3148  }
3149 
3150  public void llStopSound()
3151  {
3152  m_host.AddScriptLPS(1);
3153 
3154  if (m_SoundModule != null)
3155  m_SoundModule.StopSound(m_host.UUID);
3156  }
3157 
3158  public void llPreloadSound(string sound)
3159  {
3160  m_host.AddScriptLPS(1);
3161  if (m_SoundModule != null)
3162  m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
3163  ScriptSleep(m_sleepMsOnPreloadSound);
3164  }
3165 
3172  public LSL_String llGetSubString(string src, int start, int end)
3173  {
3174  m_host.AddScriptLPS(1);
3175 
3176  // Normalize indices (if negative).
3177  // After normlaization they may still be
3178  // negative, but that is now relative to
3179  // the start, rather than the end, of the
3180  // sequence.
3181 
3182  if (start < 0)
3183  {
3184  start = src.Length+start;
3185  }
3186  if (end < 0)
3187  {
3188  end = src.Length+end;
3189  }
3190 
3191  // Conventional substring
3192  if (start <= end)
3193  {
3194  // Implies both bounds are out-of-range.
3195  if (end < 0 || start >= src.Length)
3196  {
3197  return String.Empty;
3198  }
3199  // If end is positive, then it directly
3200  // corresponds to the lengt of the substring
3201  // needed (plus one of course). BUT, it
3202  // must be within bounds.
3203  if (end >= src.Length)
3204  {
3205  end = src.Length-1;
3206  }
3207 
3208  if (start < 0)
3209  {
3210  return src.Substring(0,end+1);
3211  }
3212  // Both indices are positive
3213  return src.Substring(start, (end+1) - start);
3214  }
3215 
3216  // Inverted substring (end < start)
3217  else
3218  {
3219  // Implies both indices are below the
3220  // lower bound. In the inverted case, that
3221  // means the entire string will be returned
3222  // unchanged.
3223  if (start < 0)
3224  {
3225  return src;
3226  }
3227  // If both indices are greater than the upper
3228  // bound the result may seem initially counter
3229  // intuitive.
3230  if (end >= src.Length)
3231  {
3232  return src;
3233  }
3234 
3235  if (end < 0)
3236  {
3237  if (start < src.Length)
3238  {
3239  return src.Substring(start);
3240  }
3241  else
3242  {
3243  return String.Empty;
3244  }
3245  }
3246  else
3247  {
3248  if (start < src.Length)
3249  {
3250  return src.Substring(0,end+1) + src.Substring(start);
3251  }
3252  else
3253  {
3254  return src.Substring(0,end+1);
3255  }
3256  }
3257  }
3258  }
3259 
3266  public LSL_String llDeleteSubString(string src, int start, int end)
3267  {
3268  m_host.AddScriptLPS(1);
3269 
3270  // Normalize indices (if negative).
3271  // After normlaization they may still be
3272  // negative, but that is now relative to
3273  // the start, rather than the end, of the
3274  // sequence.
3275  if (start < 0)
3276  {
3277  start = src.Length+start;
3278  }
3279  if (end < 0)
3280  {
3281  end = src.Length+end;
3282  }
3283  // Conventionally delimited substring
3284  if (start <= end)
3285  {
3286  // If both bounds are outside of the existing
3287  // string, then return unchanges.
3288  if (end < 0 || start >= src.Length)
3289  {
3290  return src;
3291  }
3292  // At least one bound is in-range, so we
3293  // need to clip the out-of-bound argument.
3294  if (start < 0)
3295  {
3296  start = 0;
3297  }
3298 
3299  if (end >= src.Length)
3300  {
3301  end = src.Length-1;
3302  }
3303 
3304  return src.Remove(start,end-start+1);
3305  }
3306  // Inverted substring
3307  else
3308  {
3309  // In this case, out of bounds means that
3310  // the existing string is part of the cut.
3311  if (start < 0 || end >= src.Length)
3312  {
3313  return String.Empty;
3314  }
3315 
3316  if (end > 0)
3317  {
3318  if (start < src.Length)
3319  {
3320  return src.Remove(start).Remove(0,end+1);
3321  }
3322  else
3323  {
3324  return src.Remove(0,end+1);
3325  }
3326  }
3327  else
3328  {
3329  if (start < src.Length)
3330  {
3331  return src.Remove(start);
3332  }
3333  else
3334  {
3335  return src;
3336  }
3337  }
3338  }
3339  }
3340 
3347  public LSL_String llInsertString(string dest, int index, string src)
3348  {
3349  m_host.AddScriptLPS(1);
3350 
3351  // Normalize indices (if negative).
3352  // After normlaization they may still be
3353  // negative, but that is now relative to
3354  // the start, rather than the end, of the
3355  // sequence.
3356  if (index < 0)
3357  {
3358  index = dest.Length+index;
3359 
3360  // Negative now means it is less than the lower
3361  // bound of the string.
3362 
3363  if (index < 0)
3364  {
3365  return src+dest;
3366  }
3367 
3368  }
3369 
3370  if (index >= dest.Length)
3371  {
3372  return dest+src;
3373  }
3374 
3375  // The index is in bounds.
3376  // In this case the index refers to the index that will
3377  // be assigned to the first character of the inserted string.
3378  // So unlike the other string operations, we do not add one
3379  // to get the correct string length.
3380  return dest.Substring(0,index)+src+dest.Substring(index);
3381 
3382  }
3383 
3384  public LSL_String llToUpper(string src)
3385  {
3386  m_host.AddScriptLPS(1);
3387  return src.ToUpper();
3388  }
3389 
3390  public LSL_String llToLower(string src)
3391  {
3392  m_host.AddScriptLPS(1);
3393  return src.ToLower();
3394  }
3395 
3396  public LSL_Integer llGiveMoney(string destination, int amount)
3397  {
3398  Util.FireAndForget(x =>
3399  {
3400  m_host.AddScriptLPS(1);
3401 
3402  if (m_item.PermsGranter == UUID.Zero)
3403  return;
3404 
3405  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
3406  {
3407  Error("llGiveMoney", "No permissions to give money");
3408  return;
3409  }
3410 
3411  UUID toID = new UUID();
3412 
3413  if (!UUID.TryParse(destination, out toID))
3414  {
3415  Error("llGiveMoney", "Bad key in llGiveMoney");
3416  return;
3417  }
3418 
3419  IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
3420 
3421  if (money == null)
3422  {
3423  NotImplemented("llGiveMoney");
3424  return;
3425  }
3426 
3427  string reason;
3428  money.ObjectGiveMoney(
3429 
3430  m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero, out reason);
3431  }, null, "LSL_Api.llGiveMoney");
3432 
3433  return 0;
3434  }
3435 
3436  public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3437  {
3438  m_host.AddScriptLPS(1);
3439  Deprecated("llMakeExplosion", "Use llParticleSystem instead");
3440  ScriptSleep(m_sleepMsOnMakeExplosion);
3441  }
3442 
3443  public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
3444  {
3445  m_host.AddScriptLPS(1);
3446  Deprecated("llMakeFountain", "Use llParticleSystem instead");
3447  ScriptSleep(m_sleepMsOnMakeFountain);
3448  }
3449 
3450  public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3451  {
3452  m_host.AddScriptLPS(1);
3453  Deprecated("llMakeSmoke", "Use llParticleSystem instead");
3454  ScriptSleep(m_sleepMsOnMakeSmoke);
3455  }
3456 
3457  public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3458  {
3459  m_host.AddScriptLPS(1);
3460  Deprecated("llMakeFire", "Use llParticleSystem instead");
3461  ScriptSleep(m_sleepMsOnMakeFire);
3462  }
3463 
3464  public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
3465  {
3466  doObjectRez(inventory, pos, vel, rot, param, true);
3467  }
3468 
3469  public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot)
3470  {
3471  m_host.AddScriptLPS(1);
3472 
3473  Util.FireAndForget(x =>
3474  {
3475  if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
3476  return;
3477 
3478  float dist = (float)llVecDist(llGetPos(), pos);
3479 
3480  if (dist > m_ScriptDistanceFactor * 10.0f)
3481  return;
3482 
3483  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
3484 
3485  if (item == null)
3486  {
3487  Error("llRezAtRoot", "Can't find object '" + inventory + "'");
3488  return;
3489  }
3490 
3491  if (item.InvType != (int)InventoryType.Object)
3492  {
3493  Error("llRezAtRoot", "Can't create requested object; object is missing from database");
3494  return;
3495  }
3496 
3497  List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param, atRoot);
3498 
3499  // If either of these are null, then there was an unknown error.
3500  if (new_groups == null)
3501  return;
3502 
3503  bool notAttachment = !m_host.ParentGroup.IsAttachment;
3504 
3505  foreach (SceneObjectGroup group in new_groups)
3506  {
3507  // objects rezzed with this method are die_at_edge by default.
3508  group.RootPart.SetDieAtEdge(true);
3509 
3510  group.ResumeScripts();
3511 
3512  m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
3513  "object_rez", new Object[] {
3514  new LSL_String(
3515  group.RootPart.UUID.ToString()) },
3516  new DetectParams[0]));
3517 
3518  if (notAttachment)
3519  {
3520  float groupmass = group.GetMass();
3521 
3522  PhysicsActor pa = group.RootPart.PhysActor;
3523 
3524  //Recoil.
3525  if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3526  {
3527  Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3528  if (recoil != Vector3.Zero)
3529  {
3530  llApplyImpulse(recoil, 0);
3531  }
3532  }
3533  }
3534  // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3535  }
3536 
3537  }, null, "LSL_Api.llRezAtRoot");
3538 
3539  //ScriptSleep((int)((groupmass * velmag) / 10));
3540  ScriptSleep(m_sleepMsOnRezAtRoot);
3541  }
3542 
3543  public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
3544  {
3545  doObjectRez(inventory, pos, vel, rot, param, false);
3546  }
3547 
3548  public void llLookAt(LSL_Vector target, double strength, double damping)
3549  {
3550  m_host.AddScriptLPS(1);
3551 
3552  // Get the normalized vector to the target
3553  LSL_Vector from = llGetPos();
3554 
3555  // normalized direction to target
3556  LSL_Vector dir = llVecNorm(target - from);
3557 
3558  // use vertical to help compute left axis
3559 // LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
3560  // find normalized left axis parallel to horizon
3561 // LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
3562 
3563  LSL_Vector left = new LSL_Vector(-dir.y, dir.x, 0.0f);
3564  left = llVecNorm(left);
3565  // make up orthogonal to left and dir
3566  LSL_Vector up = LSL_Vector.Cross(dir, left);
3567 
3568  // compute rotation based on orthogonal axes
3569  // and rotate so Z points to target with X below horizont
3570  LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up);
3571 
3572  SceneObjectGroup sog = m_host.ParentGroup;
3573  if(sog == null || sog.IsDeleted)
3574  return;
3575 
3576  if (!sog.UsesPhysics || sog.IsAttachment)
3577  {
3578  // Do nothing if either value is 0 (this has been checked in SL)
3579  if (strength <= 0.0 || damping <= 0.0)
3580  return;
3581 
3582  llSetLocalRot(rot);
3583  }
3584  else
3585  {
3586  if (strength == 0)
3587  {
3588  llSetLocalRot(rot);
3589  return;
3590  }
3591 
3592  sog.StartLookAt(rot, (float)strength, (float)damping);
3593  }
3594  }
3595 
3596  public void llStopLookAt()
3597  {
3598  m_host.AddScriptLPS(1);
3599  m_host.StopLookAt();
3600  }
3601 
3602  public void llSetTimerEvent(double sec)
3603  {
3604  if (sec != 0.0 && sec < m_MinTimerInterval)
3605  sec = m_MinTimerInterval;
3606  m_host.AddScriptLPS(1);
3607  // Setting timer repeat
3608  AsyncCommands.TimerPlugin.SetTimerEvent(m_host.LocalId, m_item.ItemID, sec);
3609  }
3610 
3611  public virtual void llSleep(double sec)
3612  {
3613 // m_log.Info("llSleep snoozing " + sec + "s.");
3614  m_host.AddScriptLPS(1);
3615 
3616  Sleep((int)(sec * 1000));
3617  }
3618 
3620  {
3621  m_host.AddScriptLPS(1);
3622 
3623  if (m_host.ParentGroup.IsAttachment)
3624  {
3625  ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
3626 
3627  if (attachedAvatar != null)
3628  {
3629  return attachedAvatar.GetMass();
3630  }
3631  else
3632  {
3633  return 0;
3634  }
3635  }
3636  else
3637  {
3638  // new SL always returns object mass
3639 // if (m_host.IsRoot)
3640 // {
3641  return m_host.ParentGroup.GetMass();
3642 // }
3643 // else
3644 // {
3645 // return m_host.GetMass();
3646 // }
3647  }
3648  }
3649 
3651  {
3652  return 100f * llGetMass();
3653  }
3654 
3655  public void llCollisionFilter(string name, string id, int accept)
3656  {
3657  m_host.AddScriptLPS(1);
3658  m_host.CollisionFilter.Clear();
3659  UUID objectID;
3660 
3661  if (!UUID.TryParse(id, out objectID))
3662  objectID = UUID.Zero;
3663 
3664  if (objectID == UUID.Zero && name == "")
3665  return;
3666 
3667  m_host.CollisionFilter.Add(accept,objectID.ToString() + name);
3668  }
3669 
3670  public void llTakeControls(int controls, int accept, int pass_on)
3671  {
3672  if (m_item.PermsGranter != UUID.Zero)
3673  {
3674  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3675 
3676  if (presence != null)
3677  {
3678  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
3679  {
3680  presence.RegisterControlEventsToScript(controls, accept, pass_on, m_host.LocalId, m_item.ItemID);
3681  }
3682  }
3683  }
3684 
3685  m_host.AddScriptLPS(1);
3686  }
3687 
3688  public void llReleaseControls()
3689  {
3690  m_host.AddScriptLPS(1);
3691 
3692  if (m_item.PermsGranter != UUID.Zero)
3693  {
3694  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3695 
3696  if (presence != null)
3697  {
3698  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
3699  {
3700  // Unregister controls from Presence
3701  presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
3702  // Remove Take Control permission.
3703  m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3704  }
3705  }
3706  }
3707  }
3708 
3709  public void llReleaseURL(string url)
3710  {
3711  m_host.AddScriptLPS(1);
3712  if (m_UrlModule != null)
3713  m_UrlModule.ReleaseURL(url);
3714  }
3715 
3723  public bool AttachToAvatar(int attachmentPoint)
3724  {
3725  SceneObjectGroup grp = m_host.ParentGroup;
3726  ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
3727 
3728  IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3729 
3730  if (attachmentsModule != null)
3731  return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true);
3732  else
3733  return false;
3734  }
3735 
3742  public void DetachFromAvatar()
3743  {
3744  Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar");
3745  }
3746 
3747  private void DetachWrapper(object o)
3748  {
3749  if (World.AttachmentsModule != null)
3750  {
3751  SceneObjectPart host = (SceneObjectPart)o;
3752  ScenePresence presence = World.GetScenePresence(host.OwnerID);
3753  World.AttachmentsModule.DetachSingleAttachmentToInv(presence, host.ParentGroup);
3754  }
3755  }
3756 
3757  public void llAttachToAvatar(int attachmentPoint)
3758  {
3759  m_host.AddScriptLPS(1);
3760 
3761  if (m_item.PermsGranter != m_host.OwnerID)
3762  return;
3763 
3764  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
3765  AttachToAvatar(attachmentPoint);
3766  }
3767 
3768  public void llDetachFromAvatar()
3769  {
3770  m_host.AddScriptLPS(1);
3771 
3772  if (m_host.ParentGroup.AttachmentPoint == 0)
3773  return;
3774 
3775  if (m_item.PermsGranter != m_host.OwnerID)
3776  return;
3777 
3778  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
3779  DetachFromAvatar();
3780  }
3781 
3782  public void llTakeCamera(string avatar)
3783  {
3784  m_host.AddScriptLPS(1);
3785  Deprecated("llTakeCamera", "Use llSetCameraParams instead");
3786  }
3787 
3788  public void llReleaseCamera(string avatar)
3789  {
3790  m_host.AddScriptLPS(1);
3791  Deprecated("llReleaseCamera", "Use llClearCameraParams instead");
3792  }
3793 
3795  {
3796  m_host.AddScriptLPS(1);
3797 
3798  return m_host.OwnerID.ToString();
3799  }
3800 
3801  public void llInstantMessage(string user, string message)
3802  {
3803  m_host.AddScriptLPS(1);
3804  UUID result;
3805  if (!UUID.TryParse(user, out result) || result == UUID.Zero)
3806  {
3807  Error("llInstantMessage","An invalid key was passed to llInstantMessage");
3808  ScriptSleep(2000);
3809  return;
3810  }
3811 
3812  // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
3813  // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
3814  // but I don't think we have a list of scenes available from here.
3815  // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
3816 
3817  // user is a UUID
3818 
3819  // TODO: figure out values for client, fromSession, and imSessionID
3820  // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
3821  UUID friendTransactionID = UUID.Random();
3822 
3823  //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3824 
3826  msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid;
3827  msg.toAgentID = new Guid(user); // toAgentID.Guid;
3828  msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here
3829  msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3830  msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
3831 
3832  if (message != null && message.Length > 1024)
3833  msg.message = message.Substring(0, 1024);
3834  else
3835  msg.message = message;
3836  msg.dialog = (byte)19; // MessageFromObject
3837  msg.fromGroup = false;// fromGroup;
3838  msg.offline = (byte)0; //offline;
3839  msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3840  msg.Position = new Vector3(m_host.AbsolutePosition);
3841  msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
3842 
3843  Vector3 pos = m_host.AbsolutePosition;
3844  msg.binaryBucket
3845  = Util.StringToBytes256(
3846  "{0}/{1}/{2}/{3}",
3847  World.RegionInfo.RegionName,
3848  (int)Math.Floor(pos.X),
3849  (int)Math.Floor(pos.Y),
3850  (int)Math.Floor(pos.Z));
3851 
3852  if (m_TransferModule != null)
3853  {
3854  m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
3855  }
3856 
3857  ScriptSleep(m_sleepMsOnInstantMessage);
3858  }
3859 
3860  public void llEmail(string address, string subject, string message)
3861  {
3862  m_host.AddScriptLPS(1);
3863  IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
3864  if (emailModule == null)
3865  {
3866  Error("llEmail", "Email module not configured");
3867  return;
3868  }
3869 
3870  //Restrict email destination to the avatars registered email address?
3871  //The restriction only applies if the destination address is not local.
3872  if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false)
3873  {
3874  UserAccount account =
3875  World.UserAccountService.GetUserAccount(
3876  World.RegionInfo.ScopeID,
3877  m_host.OwnerID);
3878 
3879  if (account == null)
3880  {
3881  Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'");
3882  return;
3883  }
3884 
3885  if (String.IsNullOrEmpty(account.Email))
3886  {
3887  Error("llEmail", "User account has not registered an email address.");
3888  return;
3889  }
3890 
3891  address = account.Email;
3892  }
3893 
3894  emailModule.SendEmail(m_host.UUID, address, subject, message);
3895  ScriptSleep(m_sleepMsOnEmail);
3896  }
3897 
3898  public void llGetNextEmail(string address, string subject)
3899  {
3900  m_host.AddScriptLPS(1);
3901  IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
3902  if (emailModule == null)
3903  {
3904  Error("llGetNextEmail", "Email module not configured");
3905  return;
3906  }
3907  Email email;
3908 
3909  email = emailModule.GetNextEmail(m_host.UUID, address, subject);
3910 
3911  if (email == null)
3912  return;
3913 
3914  m_ScriptEngine.PostObjectEvent(m_host.LocalId,
3915  new EventParams("email",
3916  new Object[] {
3917  new LSL_String(email.time),
3918  new LSL_String(email.sender),
3919  new LSL_String(email.subject),
3920  new LSL_String(email.message),
3921  new LSL_Integer(email.numLeft)},
3922  new DetectParams[0]));
3923 
3924  }
3925 
3927  {
3928  m_host.AddScriptLPS(1);
3929  return m_host.UUID.ToString();
3930  }
3931 
3933  {
3934  m_host.AddScriptLPS(1);
3935  return UUID.Random().ToString();
3936  }
3937 
3938  public void llSetBuoyancy(double buoyancy)
3939  {
3940  m_host.AddScriptLPS(1);
3941 
3942  if (!m_host.ParentGroup.IsDeleted)
3943  {
3944  m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
3945  }
3946  }
3947 
3954  public void llSetHoverHeight(double height, int water, double tau)
3955  {
3956  m_host.AddScriptLPS(1);
3957 
3958  PIDHoverType hoverType = PIDHoverType.Ground;
3959  if (water != 0)
3960  {
3961  hoverType = PIDHoverType.GroundAndWater;
3962  }
3963  m_host.SetHoverHeight((float)height, hoverType, (float)tau);
3964  }
3965 
3966  public void llStopHover()
3967  {
3968  m_host.AddScriptLPS(1);
3969  m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
3970  }
3971 
3972  public void llMinEventDelay(double delay)
3973  {
3974  m_host.AddScriptLPS(1);
3975  try
3976  {
3977  m_ScriptEngine.SetMinEventDelay(m_item.ItemID, delay);
3978  }
3979  catch (NotImplementedException)
3980  {
3981  // Currently not implemented in DotNetEngine only XEngine
3982  NotImplemented("llMinEventDelay", "In DotNetEngine");
3983  }
3984  }
3985 
3986  public void llSoundPreload(string sound)
3987  {
3988  m_host.AddScriptLPS(1);
3989  Deprecated("llSoundPreload", "Use llPreloadSound instead");
3990  }
3991 
3992  public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3993  {
3994  m_host.AddScriptLPS(1);
3995 
3996  // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
3997  // set the rotation of the object, copy that behavior
3998  SceneObjectGroup sog = m_host.ParentGroup;
3999  if(sog == null || sog.IsDeleted)
4000  return;
4001 
4002  if (strength == 0 || !sog.UsesPhysics || sog.IsAttachment)
4003  {
4004  llSetLocalRot(target);
4005  }
4006  else
4007  {
4008  sog.RotLookAt(target, (float)strength, (float)damping);
4009  }
4010  }
4011 
4012  public LSL_Integer llStringLength(string str)
4013  {
4014  m_host.AddScriptLPS(1);
4015  if (str.Length > 0)
4016  {
4017  return str.Length;
4018  }
4019  else
4020  {
4021  return 0;
4022  }
4023  }
4024 
4025  public void llStartAnimation(string anim)
4026  {
4027  m_host.AddScriptLPS(1);
4028 
4029  if (m_item.PermsGranter == UUID.Zero)
4030  return;
4031 
4032  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
4033  {
4034  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
4035 
4036  if (presence != null)
4037  {
4038  // Do NOT try to parse UUID, animations cannot be triggered by ID
4039  UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
4040  if (animID == UUID.Zero)
4041  presence.Animator.AddAnimation(anim, m_host.UUID);
4042  else
4043  presence.Animator.AddAnimation(animID, m_host.UUID);
4044  }
4045  }
4046  }
4047 
4048  public void llStopAnimation(string anim)
4049  {
4050  m_host.AddScriptLPS(1);
4051 
4052  if (m_item.PermsGranter == UUID.Zero)
4053  return;
4054 
4055  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
4056  {
4057  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
4058 
4059  if (presence != null)
4060  {
4061  UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim);
4062 
4063  if (animID == UUID.Zero)
4064  presence.Animator.RemoveAnimation(anim);
4065  else
4066  presence.Animator.RemoveAnimation(animID, true);
4067  }
4068  }
4069  }
4070 
4071  public void llPointAt(LSL_Vector pos)
4072  {
4073  m_host.AddScriptLPS(1);
4074  }
4075 
4076  public void llStopPointAt()
4077  {
4078  m_host.AddScriptLPS(1);
4079  }
4080 
4081  public void llTargetOmega(LSL_Vector axis, double spinrate, double gain)
4082  {
4083  m_host.AddScriptLPS(1);
4084  TargetOmega(m_host, axis, spinrate, gain);
4085  }
4086 
4087  protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
4088  {
4089  PhysicsActor pa = part.PhysActor;
4090  if ( ( pa == null || !pa.IsPhysical ) && gain == 0.0d )
4091  spinrate = 0.0d;
4092  part.UpdateAngularVelocity(axis * spinrate);
4093  }
4094 
4096  {
4097  m_host.AddScriptLPS(1);
4098  return m_ScriptEngine.GetStartParameter(m_item.ItemID);
4099  }
4100 
4101  public void llRequestPermissions(string agent, int perm)
4102  {
4103  UUID agentID;
4104 
4105  if (!UUID.TryParse(agent, out agentID))
4106  return;
4107 
4108  if (agentID == UUID.Zero || perm == 0) // Releasing permissions
4109  {
4110  llReleaseControls();
4111 
4112  m_item.PermsGranter = UUID.Zero;
4113  m_item.PermsMask = 0;
4114 
4115  m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
4116  "run_time_permissions", new Object[] {
4117  new LSL_Integer(0) },
4118  new DetectParams[0]));
4119 
4120  return;
4121  }
4122 
4123  if (m_item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
4124  llReleaseControls();
4125 
4126  m_host.AddScriptLPS(1);
4127 
4128  int implicitPerms = 0;
4129 
4130  if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar)
4131  {
4132  // When attached, certain permissions are implicit if requested from owner
4133  implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
4134  ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
4135  ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
4136  ScriptBaseClass.PERMISSION_TRACK_CAMERA |
4137  ScriptBaseClass.PERMISSION_ATTACH |
4138  ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS;
4139  }
4140  else
4141  {
4142  if (m_host.ParentGroup.GetSittingAvatars().SingleOrDefault(sp => sp.UUID == agentID) != null)
4143  {
4144  // When agent is sitting, certain permissions are implicit if requested from sitting agent
4145  implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
4146  ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
4147  ScriptBaseClass.PERMISSION_TRACK_CAMERA |
4148  ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
4149  }
4150  else
4151  {
4152  if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
4153  implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
4154  }
4155  if (World.GetExtraSetting("auto_grant_all_perms") == "true")
4156  {
4157  implicitPerms = perm;
4158  }
4159  }
4160 
4161  if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
4162  {
4163  m_host.TaskInventory.LockItemsForWrite(true);
4164  m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
4165  m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
4166  m_host.TaskInventory.LockItemsForWrite(false);
4167 
4168  m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
4169  "run_time_permissions", new Object[] {
4170  new LSL_Integer(perm) },
4171  new DetectParams[0]));
4172 
4173  return;
4174  }
4175 
4176  ScenePresence presence = World.GetScenePresence(agentID);
4177 
4178  if (presence != null)
4179  {
4180  // If permissions are being requested from an NPC and were not implicitly granted above then
4181  // auto grant all requested permissions if the script is owned by the NPC or the NPCs owner
4182  INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
4183  if (npcModule != null && npcModule.IsNPC(agentID, World))
4184  {
4185  if (npcModule.CheckPermissions(agentID, m_host.OwnerID))
4186  {
4187  lock (m_host.TaskInventory)
4188  {
4189  m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
4190  m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
4191  }
4192 
4193  m_ScriptEngine.PostScriptEvent(
4194  m_item.ItemID,
4195  new EventParams(
4196  "run_time_permissions", new Object[] { new LSL_Integer(perm) }, new DetectParams[0]));
4197  }
4198 
4199  // it is an NPC, exit even if the permissions werent granted above, they are not going to answer
4200  // the question!
4201  return;
4202  }
4203 
4204  string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID);
4205  if (ownerName == String.Empty)
4206  ownerName = "(hippos)";
4207 
4208  if (!m_waitingForScriptAnswer)
4209  {
4210  m_host.TaskInventory.LockItemsForWrite(true);
4211  m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
4212  m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
4213  m_host.TaskInventory.LockItemsForWrite(false);
4214 
4215  presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
4216  m_waitingForScriptAnswer=true;
4217  }
4218 
4219  presence.ControllingClient.SendScriptQuestion(
4220  m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, m_item.ItemID, perm);
4221 
4222  return;
4223  }
4224 
4225  // Requested agent is not in range, refuse perms
4226  m_ScriptEngine.PostScriptEvent(
4227  m_item.ItemID,
4228  new EventParams("run_time_permissions", new Object[] { new LSL_Integer(0) }, new DetectParams[0]));
4229  }
4230 
4231  void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
4232  {
4233  if (taskID != m_host.UUID)
4234  return;
4235 
4236  client.OnScriptAnswer -= handleScriptAnswer;
4237  m_waitingForScriptAnswer = false;
4238 
4239  if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
4240  llReleaseControls();
4241 
4242  m_host.TaskInventory.LockItemsForWrite(true);
4243  m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
4244  m_host.TaskInventory.LockItemsForWrite(false);
4245 
4246  m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
4247  "run_time_permissions", new Object[] {
4248  new LSL_Integer(answer) },
4249  new DetectParams[0]));
4250  }
4251 
4253  {
4254  m_host.AddScriptLPS(1);
4255 
4256  return m_item.PermsGranter.ToString();
4257  }
4258 
4260  {
4261  m_host.AddScriptLPS(1);
4262 
4263  int perms = m_item.PermsMask;
4264 
4265  if (m_automaticLinkPermission)
4266  perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
4267 
4268  return perms;
4269  }
4270 
4272  {
4273  m_host.AddScriptLPS(1);
4274 
4275  if (m_host.ParentGroup.PrimCount > 1)
4276  {
4277  return m_host.LinkNum;
4278  }
4279  else
4280  {
4281  return 0;
4282  }
4283  }
4284 
4285  public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
4286  {
4287  List<SceneObjectPart> parts = GetLinkParts(linknumber);
4288  if (parts.Count > 0)
4289  {
4290  try
4291  {
4292  foreach (SceneObjectPart part in parts)
4293  part.SetFaceColorAlpha(face, color, null);
4294  }
4295  finally { }
4296  }
4297  }
4298 
4299  public void llCreateLink(string target, int parent)
4300  {
4301  m_host.AddScriptLPS(1);
4302 
4303  UUID targetID;
4304 
4305  if (!UUID.TryParse(target, out targetID))
4306  return;
4307 
4308  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4309  && !m_automaticLinkPermission)
4310  {
4311  Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set");
4312  return;
4313  }
4314 
4315  CreateLink(target, parent);
4316  }
4317 
4318  public void CreateLink(string target, int parent)
4319  {
4320  UUID targetID;
4321 
4322  if (!UUID.TryParse(target, out targetID))
4323  return;
4324 
4325  SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID);
4326 
4327  if (targetPart.ParentGroup.AttachmentPoint != 0)
4328  return; // Fail silently if attached
4329 
4330  if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
4331  return;
4332 
4333  SceneObjectGroup parentPrim = null, childPrim = null;
4334 
4335  if (targetPart != null)
4336  {
4337  if (parent != 0)
4338  {
4339  parentPrim = m_host.ParentGroup;
4340  childPrim = targetPart.ParentGroup;
4341  }
4342  else
4343  {
4344  parentPrim = targetPart.ParentGroup;
4345  childPrim = m_host.ParentGroup;
4346  }
4347 
4348  // Required for linking
4349  childPrim.RootPart.ClearUpdateSchedule();
4350  parentPrim.LinkToGroup(childPrim, true);
4351  }
4352 
4353  parentPrim.TriggerScriptChangedEvent(Changed.LINK);
4354  parentPrim.RootPart.CreateSelected = true;
4355  parentPrim.HasGroupChanged = true;
4356  parentPrim.ScheduleGroupForFullUpdate();
4357 
4358  IClientAPI client = null;
4359  ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
4360  if (sp != null)
4361  client = sp.ControllingClient;
4362 
4363  if (client != null)
4364  parentPrim.SendPropertiesToClient(client);
4365 
4366  ScriptSleep(m_sleepMsOnCreateLink);
4367  }
4368 
4369  public void llBreakLink(int linknum)
4370  {
4371  m_host.AddScriptLPS(1);
4372 
4373  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4374  && !m_automaticLinkPermission)
4375  {
4376  Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set");
4377  return;
4378  }
4379 
4380  BreakLink(linknum);
4381  }
4382 
4383  public void BreakLink(int linknum)
4384  {
4385  if (linknum < ScriptBaseClass.LINK_THIS)
4386  return;
4387 
4388  SceneObjectGroup parentPrim = m_host.ParentGroup;
4389 
4390  if (parentPrim.AttachmentPoint != 0)
4391  return; // Fail silently if attached
4392  SceneObjectPart childPrim = null;
4393 
4394  switch (linknum)
4395  {
4396  case ScriptBaseClass.LINK_ROOT:
4397  break;
4398  case ScriptBaseClass.LINK_SET:
4399  case ScriptBaseClass.LINK_ALL_OTHERS:
4400  case ScriptBaseClass.LINK_ALL_CHILDREN:
4401  case ScriptBaseClass.LINK_THIS:
4402  foreach (SceneObjectPart part in parentPrim.Parts)
4403  {
4404  if (part.UUID != m_host.UUID)
4405  {
4406  childPrim = part;
4407  break;
4408  }
4409  }
4410  break;
4411  default:
4412  childPrim = parentPrim.GetLinkNumPart(linknum);
4413  if (childPrim.UUID == m_host.UUID)
4414  childPrim = null;
4415  break;
4416  }
4417 
4418  if (linknum == ScriptBaseClass.LINK_ROOT)
4419  {
4420  // Restructuring Multiple Prims.
4421  List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
4422  parts.Remove(parentPrim.RootPart);
4423  if (parts.Count > 0)
4424  {
4425  try
4426  {
4427  foreach (SceneObjectPart part in parts)
4428  {
4429  parentPrim.DelinkFromGroup(part.LocalId, true);
4430  }
4431  }
4432  finally { }
4433  }
4434 
4435  parentPrim.HasGroupChanged = true;
4436  parentPrim.ScheduleGroupForFullUpdate();
4437  parentPrim.TriggerScriptChangedEvent(Changed.LINK);
4438 
4439  if (parts.Count > 0)
4440  {
4441  SceneObjectPart newRoot = parts[0];
4442  parts.Remove(newRoot);
4443 
4444  try
4445  {
4446  foreach (SceneObjectPart part in parts)
4447  {
4448  part.ClearUpdateSchedule();
4449  newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4450  }
4451  }
4452  finally { }
4453 
4454  newRoot.ParentGroup.HasGroupChanged = true;
4455  newRoot.ParentGroup.ScheduleGroupForFullUpdate();
4456  }
4457  }
4458  else
4459  {
4460  if (childPrim == null)
4461  return;
4462 
4463  parentPrim.DelinkFromGroup(childPrim.LocalId, true);
4464  parentPrim.HasGroupChanged = true;
4465  parentPrim.ScheduleGroupForFullUpdate();
4466  parentPrim.TriggerScriptChangedEvent(Changed.LINK);
4467  }
4468  }
4469 
4470  public void llBreakAllLinks()
4471  {
4472  m_host.AddScriptLPS(1);
4473 
4474  TaskInventoryItem item = m_item;
4475 
4476  if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4477  && !m_automaticLinkPermission)
4478  {
4479  Error("llBreakAllLinks","Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4480  return;
4481  }
4482  BreakAllLinks();
4483  }
4484 
4485  public void BreakAllLinks()
4486  {
4487  SceneObjectGroup parentPrim = m_host.ParentGroup;
4488  if (parentPrim.AttachmentPoint != 0)
4489  return; // Fail silently if attached
4490 
4491  List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
4492  parts.Remove(parentPrim.RootPart);
4493 
4494  foreach (SceneObjectPart part in parts)
4495  {
4496  parentPrim.DelinkFromGroup(part.LocalId, true);
4497  parentPrim.TriggerScriptChangedEvent(Changed.LINK);
4498  }
4499  parentPrim.HasGroupChanged = true;
4500  parentPrim.ScheduleGroupForFullUpdate();
4501  }
4502 
4503  public LSL_String llGetLinkKey(int linknum)
4504  {
4505  m_host.AddScriptLPS(1);
4506  SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
4507  if (part != null)
4508  {
4509  return part.UUID.ToString();
4510  }
4511  else
4512  {
4513  if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4514  {
4515  linknum -= (m_host.ParentGroup.PrimCount) + 1;
4516 
4517  if (linknum < 0)
4518  return UUID.Zero.ToString();
4519 
4520  List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4521  if (avatars.Count > linknum)
4522  {
4523  return avatars[linknum].UUID.ToString();
4524  }
4525  }
4526  return UUID.Zero.ToString();
4527  }
4528  }
4529 
4569  public LSL_String llGetLinkName(int linknum)
4570  {
4571  m_host.AddScriptLPS(1);
4572 
4573  ISceneEntity entity = GetLinkEntity(m_host, linknum);
4574 
4575  if (entity != null)
4576  return entity.Name;
4577  else
4578  return ScriptBaseClass.NULL_KEY;
4579  }
4580 
4582  {
4583  m_host.AddScriptLPS(1);
4584  int count = 0;
4585 
4586  m_host.TaskInventory.LockItemsForRead(true);
4587  foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4588  {
4589  if (inv.Value.Type == type || type == -1)
4590  {
4591  count = count + 1;
4592  }
4593  }
4594 
4595  m_host.TaskInventory.LockItemsForRead(false);
4596  return count;
4597  }
4598 
4599  public LSL_String llGetInventoryName(int type, int number)
4600  {
4601  m_host.AddScriptLPS(1);
4602  ArrayList keys = new ArrayList();
4603 
4604  m_host.TaskInventory.LockItemsForRead(true);
4605  foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4606  {
4607  if (inv.Value.Type == type || type == -1)
4608  {
4609  keys.Add(inv.Value.Name);
4610  }
4611  }
4612  m_host.TaskInventory.LockItemsForRead(false);
4613 
4614  if (keys.Count == 0)
4615  {
4616  return String.Empty;
4617  }
4618  keys.Sort();
4619  if (keys.Count > number)
4620  {
4621  return (string)keys[number];
4622  }
4623  return String.Empty;
4624  }
4625 
4627  {
4628  m_host.AddScriptLPS(1);
4629  // TODO: figure out real energy value
4630  return 1.0f;
4631  }
4632 
4633  public void llGiveInventory(string destination, string inventory)
4634  {
4635  m_host.AddScriptLPS(1);
4636 
4637  UUID destId = UUID.Zero;
4638 
4639  if (!UUID.TryParse(destination, out destId))
4640  {
4641  Error("llGiveInventory", "Can't parse destination key '" + destination + "'");
4642  return;
4643  }
4644 
4645  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
4646 
4647  if (item == null)
4648  {
4649  Error("llGiveInventory", "Can't find inventory object '" + inventory + "'");
4650  return;
4651  }
4652 
4653  UUID objId = item.ItemID;
4654 
4655  // check if destination is an object
4656  if (World.GetSceneObjectPart(destId) != null)
4657  {
4658  // destination is an object
4659  World.MoveTaskInventoryItem(destId, m_host, objId);
4660  }
4661  else
4662  {
4663  ScenePresence presence = World.GetScenePresence(destId);
4664 
4665  if (presence == null)
4666  {
4667  UserAccount account =
4668  World.UserAccountService.GetUserAccount(
4669  World.RegionInfo.ScopeID,
4670  destId);
4671 
4672  if (account == null)
4673  {
4674  GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString());
4675  if(info == null || info.Online == false)
4676  {
4677  Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'");
4678  return;
4679  }
4680  }
4681  }
4682 
4683  // destination is an avatar
4684  string message;
4685  InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message);
4686 
4687  if (agentItem == null)
4688  {
4689  llSay(0, message);
4690  return;
4691  }
4692 
4693  byte[] bucket = new byte[1];
4694  bucket[0] = (byte)item.Type;
4695  //byte[] objBytes = agentItem.ID.GetBytes();
4696  //Array.Copy(objBytes, 0, bucket, 1, 16);
4697 
4699  m_host.OwnerID, m_host.Name, destId,
4700  (byte)InstantMessageDialog.TaskInventoryOffered,
4701  false, item.Name+". "+m_host.Name+" is located at "+
4702  World.RegionInfo.RegionName+" "+
4703  m_host.AbsolutePosition.ToString(),
4704  agentItem.ID, true, m_host.AbsolutePosition,
4705  bucket, true);
4706 
4707  ScenePresence sp;
4708 
4709  if (World.TryGetScenePresence(destId, out sp))
4710  {
4711  sp.ControllingClient.SendInstantMessage(msg);
4712  }
4713  else
4714  {
4715  if (m_TransferModule != null)
4716  m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4717  }
4718 
4719  //This delay should only occur when giving inventory to avatars.
4720  ScriptSleep(m_sleepMsOnGiveInventory);
4721  }
4722  }
4723 
4724  [DebuggerNonUserCode]
4725  public void llRemoveInventory(string name)
4726  {
4727  m_host.AddScriptLPS(1);
4728 
4729  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
4730 
4731  if (item == null)
4732  return;
4733 
4734  if (item.ItemID == m_item.ItemID)
4735  throw new ScriptDeleteException();
4736  else
4737  m_host.Inventory.RemoveInventoryItem(item.ItemID);
4738  }
4739 
4740  public void llSetText(string text, LSL_Vector color, double alpha)
4741  {
4742  m_host.AddScriptLPS(1);
4743  Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
4744  if (text.Length > 254)
4745  text = text.Remove(254);
4746 
4747  byte[] data;
4748  do
4749  {
4750  data = Util.UTF8.GetBytes(text);
4751  if (data.Length > 254)
4752  text = text.Substring(0, text.Length - 1);
4753  } while (data.Length > 254);
4754 
4755  m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
4756  //m_host.ParentGroup.HasGroupChanged = true;
4757  //m_host.ParentGroup.ScheduleGroupForFullUpdate();
4758  }
4759 
4761  {
4762  m_host.AddScriptLPS(1);
4763  return World.RegionInfo.RegionSettings.WaterHeight;
4764  }
4765 
4766  public void llPassTouches(int pass)
4767  {
4768  m_host.AddScriptLPS(1);
4769  if (pass != 0)
4770  m_host.PassTouches = true;
4771  else
4772  m_host.PassTouches = false;
4773  }
4774 
4775  public LSL_String llRequestAgentData(string id, int data)
4776  {
4777  m_host.AddScriptLPS(1);
4778 
4779  UUID uuid;
4780  if (UUID.TryParse(id, out uuid))
4781  {
4782  PresenceInfo pinfo = null;
4783  UserAccount account;
4784 
4785  UserInfoCacheEntry ce;
4786  if (!m_userInfoCache.TryGetValue(uuid, out ce))
4787  {
4788  account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4789  if (account == null)
4790  {
4791  m_userInfoCache[uuid] = null; // Cache negative
4792  return UUID.Zero.ToString();
4793  }
4794 
4795  PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4796  if (pinfos != null && pinfos.Length > 0)
4797  {
4798  foreach (PresenceInfo p in pinfos)
4799  {
4800  if (p.RegionID != UUID.Zero)
4801  {
4802  pinfo = p;
4803  }
4804  }
4805  }
4806 
4807  ce = new UserInfoCacheEntry();
4808  ce.time = Util.EnvironmentTickCount();
4809  ce.account = account;
4810  ce.pinfo = pinfo;
4811  m_userInfoCache[uuid] = ce;
4812  }
4813  else
4814  {
4815  if (ce == null)
4816  return UUID.Zero.ToString();
4817 
4818  account = ce.account;
4819  pinfo = ce.pinfo;
4820  }
4821 
4822  if (Util.EnvironmentTickCount() < ce.time ||
4823  (Util.EnvironmentTickCount() - ce.time) >= LlRequestAgentDataCacheTimeoutMs)
4824  {
4825  PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4826  if (pinfos != null && pinfos.Length > 0)
4827  {
4828  foreach (PresenceInfo p in pinfos)
4829  {
4830  if (p.RegionID != UUID.Zero)
4831  {
4832  pinfo = p;
4833  }
4834  }
4835  }
4836  else
4837  pinfo = null;
4838 
4839  ce.time = Util.EnvironmentTickCount();
4840  ce.pinfo = pinfo;
4841  }
4842 
4843  string reply = String.Empty;
4844 
4845  switch (data)
4846  {
4847  case ScriptBaseClass.DATA_ONLINE: // DATA_ONLINE (0|1)
4848  if (pinfo != null && pinfo.RegionID != UUID.Zero)
4849  reply = "1";
4850  else
4851  reply = "0";
4852  break;
4853  case ScriptBaseClass.DATA_NAME: // DATA_NAME (First Last)
4854  reply = account.FirstName + " " + account.LastName;
4855  break;
4856  case ScriptBaseClass.DATA_BORN: // DATA_BORN (YYYY-MM-DD)
4857  DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4858  born = born.AddSeconds(account.Created);
4859  reply = born.ToString("yyyy-MM-dd");
4860  break;
4861  case ScriptBaseClass.DATA_RATING: // DATA_RATING (0,0,0,0,0,0)
4862  reply = "0,0,0,0,0,0";
4863  break;
4864  case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant.
4865  reply = account.UserLevel.ToString();
4866  break;
4867  case ScriptBaseClass.DATA_PAYINFO: // DATA_PAYINFO (0|1|2|3)
4868  reply = "0";
4869  break;
4870  default:
4871  return UUID.Zero.ToString(); // Raise no event
4872  }
4873 
4874  UUID rq = UUID.Random();
4875 
4876  UUID tid = AsyncCommands.
4877  DataserverPlugin.RegisterRequest(m_host.LocalId,
4878  m_item.ItemID, rq.ToString());
4879 
4880  AsyncCommands.
4881  DataserverPlugin.DataserverReply(rq.ToString(), reply);
4882 
4883  ScriptSleep(m_sleepMsOnRequestAgentData);
4884  return tid.ToString();
4885  }
4886  else
4887  {
4888  Error("llRequestAgentData","Invalid UUID passed to llRequestAgentData.");
4889  }
4890  return "";
4891  }
4892 
4894  {
4895  m_host.AddScriptLPS(1);
4896 
4897  foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems())
4898  {
4899  if (item.Type == 3 && item.Name == name)
4900  {
4901  UUID tid = AsyncCommands.
4902  DataserverPlugin.RegisterRequest(m_host.LocalId,
4903  m_item.ItemID, item.AssetID.ToString());
4904 
4905  Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
4906 
4907  World.AssetService.Get(item.AssetID.ToString(), this,
4908  delegate(string i, object sender, AssetBase a)
4909  {
4910  AssetLandmark lm = new AssetLandmark(a);
4911 
4912  float rx = (uint)(lm.RegionHandle >> 32);
4913  float ry = (uint)lm.RegionHandle;
4914  region = lm.Position + new Vector3(rx, ry, 0) - region;
4915 
4916  string reply = region.ToString();
4917  AsyncCommands.
4918  DataserverPlugin.DataserverReply(i.ToString(),
4919  reply);
4920  });
4921 
4922  ScriptSleep(m_sleepMsOnRequestInventoryData);
4923  return tid.ToString();
4924  }
4925  }
4926 
4927  ScriptSleep(m_sleepMsOnRequestInventoryData);
4928  return String.Empty;
4929  }
4930 
4931  public void llSetDamage(double damage)
4932  {
4933  m_host.AddScriptLPS(1);
4934  m_host.ParentGroup.Damage = (float)damage;
4935  }
4936 
4937  public void llTeleportAgentHome(string agent)
4938  {
4939  m_host.AddScriptLPS(1);
4940  UUID agentId = new UUID();
4941  if (UUID.TryParse(agent, out agentId))
4942  {
4943  ScenePresence presence = World.GetScenePresence(agentId);
4944  if (presence != null && presence.PresenceType != PresenceType.Npc)
4945  {
4946  // agent must not be a god
4947  if (presence.UserLevel >= 200) return;
4948 
4949  // agent must be over the owners land
4950  if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4951  {
4952  if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4953  {
4954  // They can't be teleported home for some reason
4955  GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4956  if (regionInfo != null)
4957  {
4958  World.RequestTeleportLocation(
4959  presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4960  (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4961  }
4962  }
4963  }
4964  }
4965  }
4966 
4967  ScriptSleep(m_sleepMsOnSetDamage);
4968  }
4969 
4970  public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
4971  {
4972  m_host.AddScriptLPS(1);
4973  UUID agentId = new UUID();
4974 
4975  if (UUID.TryParse(agent, out agentId))
4976  {
4977  ScenePresence presence = World.GetScenePresence(agentId);
4978  if (presence != null && presence.PresenceType != PresenceType.Npc)
4979  {
4980  if (destination == String.Empty)
4981  destination = World.RegionInfo.RegionName;
4982 
4983  if (m_item.PermsGranter == agentId)
4984  {
4985  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0)
4986  {
4987  DoLLTeleport(presence, destination, targetPos, targetLookAt);
4988  }
4989  }
4990 
4991  // agent must be wearing the object
4992  if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4993  {
4994  DoLLTeleport(presence, destination, targetPos, targetLookAt);
4995  }
4996  else
4997  {
4998  // agent must not be a god
4999  if (presence.GodLevel >= 200) return;
5000 
5001  // agent must be over the owners land
5002  ILandObject agentLand = World.LandChannel.GetLandObject(presence.AbsolutePosition);
5003  ILandObject objectLand = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
5004  if (m_host.OwnerID == objectLand.LandData.OwnerID && m_host.OwnerID == agentLand.LandData.OwnerID)
5005  {
5006  DoLLTeleport(presence, destination, targetPos, targetLookAt);
5007  }
5008  }
5009  }
5010  }
5011  }
5012 
5013  public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt)
5014  {
5015  m_host.AddScriptLPS(1);
5016  UUID agentId = new UUID();
5017 
5018  ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y);
5019 
5020  if (UUID.TryParse(agent, out agentId))
5021  {
5022  // This function is owner only!
5023  if (m_host.OwnerID != agentId)
5024  return;
5025 
5026  ScenePresence presence = World.GetScenePresence(agentId);
5027 
5028  if (presence == null || presence.PresenceType == PresenceType.Npc)
5029  return;
5030 
5031  // Can't TP sitting avatars
5032  if (presence.ParentID != 0) // Sitting
5033  return;
5034 
5035  if (m_item.PermsGranter == agentId)
5036  {
5037  // If attached using llAttachToAvatarTemp, cowardly refuse
5038  if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.ParentGroup.FromItemID == UUID.Zero)
5039  return;
5040 
5041  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0)
5042  {
5043  World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
5044  }
5045  }
5046  }
5047  }
5048 
5049  private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt)
5050  {
5051  UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination);
5052 
5053  // The destinaion is not an asset ID and also doesn't name a landmark.
5054  // Use it as a sim name
5055  if (assetID == UUID.Zero)
5056  {
5057  World.RequestTeleportLocation(sp.ControllingClient, destination, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
5058  return;
5059  }
5060 
5061  AssetBase lma = World.AssetService.Get(assetID.ToString());
5062  if (lma == null)
5063  return;
5064 
5065  if (lma.Type != (sbyte)AssetType.Landmark)
5066  return;
5067 
5068  AssetLandmark lm = new AssetLandmark(lma);
5069 
5070  World.RequestTeleportLocation(sp.ControllingClient, lm.RegionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
5071  }
5072 
5073  public void llTextBox(string agent, string message, int chatChannel)
5074  {
5075  IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
5076 
5077  if (dm == null)
5078  return;
5079 
5080  m_host.AddScriptLPS(1);
5081  UUID av = new UUID();
5082  if (!UUID.TryParse(agent,out av))
5083  {
5084  Error("llTextBox", "First parameter must be a key");
5085  return;
5086  }
5087 
5088  if (message == string.Empty)
5089  {
5090  Error("llTextBox", "Empty message");
5091  }
5092  else if (Encoding.UTF8.GetByteCount(message) > 512)
5093  {
5094  Error("llTextBox", "Message longer than 512 bytes");
5095  }
5096  else
5097  {
5098  dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID);
5099  ScriptSleep(m_sleepMsOnTextBox);
5100  }
5101  }
5102 
5103  public void llModifyLand(int action, int brush)
5104  {
5105  m_host.AddScriptLPS(1);
5106  ITerrainModule tm = m_ScriptEngine.World.RequestModuleInterface<ITerrainModule>();
5107  if (tm != null)
5108  {
5109  tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte) brush, (byte) action, m_host.OwnerID);
5110  }
5111  }
5112 
5113  public void llCollisionSound(string impact_sound, double impact_volume)
5114  {
5115  m_host.AddScriptLPS(1);
5116 
5117  if(impact_sound == "")
5118  {
5119  m_host.CollisionSoundVolume = (float)impact_volume;
5120  m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
5121  m_host.CollisionSoundType = 0;
5122  return;
5123  }
5124  // TODO: Parameter check logic required.
5125  m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
5126  m_host.CollisionSoundVolume = (float)impact_volume;
5127  m_host.CollisionSoundType = 1;
5128  }
5129 
5130  public LSL_String llGetAnimation(string id)
5131  {
5132  // This should only return a value if the avatar is in the same region
5133  m_host.AddScriptLPS(1);
5134  UUID avatar = (UUID)id;
5135  ScenePresence presence = World.GetScenePresence(avatar);
5136  if (presence == null)
5137  return "";
5138 
5139  if (m_host.RegionHandle == presence.RegionHandle)
5140  {
5141  if (presence != null)
5142  {
5143 // if (presence.SitGround)
5144 // return "Sitting on Ground";
5145 // if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
5146 // return "Sitting";
5147 
5148  string movementAnimation = presence.Animator.CurrentMovementAnimation;
5149  string lslMovementAnimation;
5150 
5151  if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
5152  return lslMovementAnimation;
5153  }
5154  }
5155 
5156  return String.Empty;
5157  }
5158 
5159  public void llMessageLinked(int linknumber, int num, string msg, string id)
5160  {
5161  m_host.AddScriptLPS(1);
5162 
5163  List<SceneObjectPart> parts = GetLinkParts(linknumber);
5164 
5165  UUID partItemID;
5166  foreach (SceneObjectPart part in parts)
5167  {
5168  foreach (TaskInventoryItem item in part.Inventory.GetInventoryItems())
5169  {
5171  {
5172  partItemID = item.ItemID;
5173  int linkNumber = m_host.LinkNum;
5174  if (m_host.ParentGroup.PrimCount == 1)
5175  linkNumber = 0;
5176 
5177  object[] resobj = new object[]
5178  {
5179  new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
5180  };
5181 
5182  m_ScriptEngine.PostScriptEvent(partItemID,
5183  new EventParams("link_message",
5184  resobj, new DetectParams[0]));
5185  }
5186  }
5187  }
5188  }
5189 
5190  public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
5191  {
5192  m_host.AddScriptLPS(1);
5193  bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing;
5194  bool pushAllowed = false;
5195 
5196  bool pusheeIsAvatar = false;
5197  UUID targetID = UUID.Zero;
5198 
5199  if (!UUID.TryParse(target,out targetID))
5200  return;
5201 
5202  ScenePresence pusheeav = null;
5203  Vector3 PusheePos = Vector3.Zero;
5204  SceneObjectPart pusheeob = null;
5205 
5206  ScenePresence avatar = World.GetScenePresence(targetID);
5207  if (avatar != null)
5208  {
5209  pusheeIsAvatar = true;
5210 
5211  // Pushee doesn't have a physics actor
5212  if (avatar.PhysicsActor == null)
5213  return;
5214 
5215  // Pushee is in GodMode this pushing object isn't owned by them
5216  if (avatar.GodLevel > 0 && m_host.OwnerID != targetID)
5217  return;
5218 
5219  pusheeav = avatar;
5220 
5221  // Find pushee position
5222  // Pushee Linked?
5223  SceneObjectPart sitPart = pusheeav.ParentPart;
5224  if (sitPart != null)
5225  PusheePos = sitPart.AbsolutePosition;
5226  else
5227  PusheePos = pusheeav.AbsolutePosition;
5228  }
5229 
5230  if (!pusheeIsAvatar)
5231  {
5232  // not an avatar so push is not affected by parcel flags
5233  pusheeob = World.GetSceneObjectPart((UUID)target);
5234 
5235  // We can't find object
5236  if (pusheeob == null)
5237  return;
5238 
5239  // Object not pushable. Not an attachment and has no physics component
5240  if (!pusheeob.ParentGroup.IsAttachment && pusheeob.PhysActor == null)
5241  return;
5242 
5243  PusheePos = pusheeob.AbsolutePosition;
5244  pushAllowed = true;
5245  }
5246  else
5247  {
5248  if (pushrestricted)
5249  {
5250  ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
5251 
5252  // We didn't find the parcel but region is push restricted so assume it is NOT ok
5253  if (targetlandObj == null)
5254  return;
5255 
5256  // Need provisions for Group Owned here
5257  if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
5258  targetlandObj.LandData.IsGroupOwned || m_host.OwnerID == targetID)
5259  {
5260  pushAllowed = true;
5261  }
5262  }
5263  else
5264  {
5265  ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
5266  if (targetlandObj == null)
5267  {
5268  // We didn't find the parcel but region isn't push restricted so assume it's ok
5269  pushAllowed = true;
5270  }
5271  else
5272  {
5273  // Parcel push restriction
5274  if ((targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) == (uint)ParcelFlags.RestrictPushObject)
5275  {
5276  // Need provisions for Group Owned here
5277  if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
5278  targetlandObj.LandData.IsGroupOwned ||
5279  m_host.OwnerID == targetID)
5280  {
5281  pushAllowed = true;
5282  }
5283 
5284  //ParcelFlags.RestrictPushObject
5285  //pushAllowed = true;
5286  }
5287  else
5288  {
5289  // Parcel isn't push restricted
5290  pushAllowed = true;
5291  }
5292  }
5293  }
5294  }
5295 
5296  if (pushAllowed)
5297  {
5298  float distance = (PusheePos - m_host.AbsolutePosition).Length();
5299  float distance_term = distance * distance * distance; // Script Energy
5300  // use total object mass and not part
5301  float pusher_mass = m_host.ParentGroup.GetMass();
5302 
5303  float PUSH_ATTENUATION_DISTANCE = 17f;
5304  float PUSH_ATTENUATION_SCALE = 5f;
5305  float distance_attenuation = 1f;
5306  if (distance > PUSH_ATTENUATION_DISTANCE)
5307  {
5308  float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE;
5309  distance_attenuation = 1f / normalized_units;
5310  }
5311 
5312  Vector3 applied_linear_impulse = impulse;
5313  {
5314  float impulse_length = applied_linear_impulse.Length();
5315 
5316  float desired_energy = impulse_length * pusher_mass;
5317  if (desired_energy > 0f)
5318  desired_energy += distance_term;
5319 
5320  float scaling_factor = 1f;
5321  scaling_factor *= distance_attenuation;
5322  applied_linear_impulse *= scaling_factor;
5323 
5324  }
5325 
5326  if (pusheeIsAvatar)
5327  {
5328  if (pusheeav != null)
5329  {
5330  PhysicsActor pa = pusheeav.PhysicsActor;
5331 
5332  if (pa != null)
5333  {
5334  if (local != 0)
5335  {
5336 // applied_linear_impulse *= m_host.GetWorldRotation();
5337  applied_linear_impulse *= pusheeav.GetWorldRotation();
5338  }
5339 
5340  pa.AddForce(applied_linear_impulse, true);
5341  }
5342  }
5343  }
5344  else
5345  {
5346  if (pusheeob != null)
5347  {
5348  if (pusheeob.PhysActor != null)
5349  {
5350  pusheeob.ApplyImpulse(applied_linear_impulse, local != 0);
5351  }
5352  }
5353  }
5354  }
5355  }
5356 
5357  public void llPassCollisions(int pass)
5358  {
5359  m_host.AddScriptLPS(1);
5360  if (pass == 0)
5361  {
5362  m_host.PassCollisions = false;
5363  }
5364  else
5365  {
5366  m_host.PassCollisions = true;
5367  }
5368  }
5369 
5371  {
5372  m_host.AddScriptLPS(1);
5373 
5374  return m_item.Name != null ? m_item.Name : String.Empty;
5375  }
5376 
5378  {
5379  m_host.AddScriptLPS(1);
5380 
5381  SceneObjectPart linkedPart;
5382 
5383  if (link == ScriptBaseClass.LINK_ROOT)
5384  linkedPart = m_host.ParentGroup.RootPart;
5385  else if (link == ScriptBaseClass.LINK_THIS)
5386  linkedPart = m_host;
5387  else
5388  linkedPart = m_host.ParentGroup.GetLinkNumPart(link);
5389 
5390  return GetNumberOfSides(linkedPart);
5391  }
5392 
5394  {
5395  m_host.AddScriptLPS(1);
5396 
5397  return GetNumberOfSides(m_host);
5398  }
5399 
5400  protected int GetNumberOfSides(SceneObjectPart part)
5401  {
5402  int sides = part.GetNumberOfSides();
5403 
5404  if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0)
5405  {
5406  // Make up for a bug where LSL shows 4 sides rather than 2
5407  sides += 2;
5408  }
5409 
5410  return sides;
5411  }
5412 
5413 
5414  /* The new / changed functions were tested with the following LSL script:
5415 
5416  default
5417  {
5418  state_entry()
5419  {
5420  rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
5421 
5422  llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
5423  llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
5424 
5425  // convert back and forth between quaternion <-> vector and angle
5426 
5427  rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
5428 
5429  llOwnerSay("Old rotation was: "+(string) rot);
5430  llOwnerSay("re-converted rotation is: "+(string) newrot);
5431 
5432  llSetRot(rot); // to check the parameters in the prim
5433  }
5434  }
5435  */
5436 
5437  // Xantor 29/apr/2008
5438  // Returns rotation described by rotating angle radians about axis.
5439  // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
5440  public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle)
5441  {
5442  m_host.AddScriptLPS(1);
5443 
5444  double x, y, z, s, t;
5445 
5446  s = Math.Cos(angle * 0.5);
5447  t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs
5448  axis = LSL_Vector.Norm(axis);
5449  x = axis.x * t;
5450  y = axis.y * t;
5451  z = axis.z * t;
5452 
5453  return new LSL_Rotation(x,y,z,s);
5454  }
5455 
5462  {
5463  m_host.AddScriptLPS(1);
5464 
5465  if (Math.Abs(rot.s) > 1) // normalization needed
5466  rot.Normalize();
5467 
5468  double s = Math.Sqrt(1 - rot.s * rot.s);
5469  if (s < 0.001)
5470  {
5471  return new LSL_Vector(1, 0, 0);
5472  }
5473  else
5474  {
5475  double invS = 1.0 / s;
5476  if (rot.s < 0) invS = -invS;
5477  return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
5478  }
5479  }
5480 
5481 
5482  // Returns the angle of a quaternion (see llRot2Axis for the axis)
5484  {
5485  m_host.AddScriptLPS(1);
5486 
5487  if (Math.Abs(rot.s) > 1) // normalization needed
5488  rot.Normalize();
5489 
5490  double angle = 2 * Math.Acos(rot.s);
5491  if (angle > Math.PI)
5492  angle = 2 * Math.PI - angle;
5493 
5494  return angle;
5495  }
5496 
5497  public LSL_Float llAcos(double val)
5498  {
5499  m_host.AddScriptLPS(1);
5500  return (double)Math.Acos(val);
5501  }
5502 
5503  public LSL_Float llAsin(double val)
5504  {
5505  m_host.AddScriptLPS(1);
5506  return (double)Math.Asin(val);
5507  }
5508 
5509  // jcochran 5/jan/2012
5511  {
5512  m_host.AddScriptLPS(1);
5513 
5514  double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s);
5515  double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s);
5516  double aa_bb = aa * bb;
5517  if (aa_bb == 0) return 0.0;
5518  double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s);
5519  double quotient = (ab * ab) / aa_bb;
5520  if (quotient >= 1.0) return 0.0;
5521  return Math.Acos(2 * quotient - 1);
5522  }
5523 
5524  public LSL_String llGetInventoryKey(string name)
5525  {
5526  m_host.AddScriptLPS(1);
5527 
5528  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
5529 
5530  if (item == null)
5531  return UUID.Zero.ToString();
5532 
5533  if ((item.CurrentPermissions
5534  & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
5535  == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
5536  {
5537  return item.AssetID.ToString();
5538  }
5539 
5540  return UUID.Zero.ToString();
5541  }
5542 
5543  public void llAllowInventoryDrop(int add)
5544  {
5545  m_host.AddScriptLPS(1);
5546 
5547  if (add != 0)
5548  m_host.ParentGroup.RootPart.AllowedDrop = true;
5549  else
5550  m_host.ParentGroup.RootPart.AllowedDrop = false;
5551 
5552  // Update the object flags
5553  m_host.ParentGroup.RootPart.aggregateScriptEvents();
5554  }
5555 
5557  {
5558  m_host.AddScriptLPS(1);
5559 
5560  LSL_Vector SunDoubleVector3;
5561  Vector3 SunFloatVector3;
5562 
5563  // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule
5564  // have to convert from Vector3 (float) to LSL_Vector (double)
5565  SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
5566  SunDoubleVector3.x = (double)SunFloatVector3.X;
5567  SunDoubleVector3.y = (double)SunFloatVector3.Y;
5568  SunDoubleVector3.z = (double)SunFloatVector3.Z;
5569 
5570  return SunDoubleVector3;
5571  }
5572 
5574  {
5575  m_host.AddScriptLPS(1);
5576  return GetTextureOffset(m_host, face);
5577  }
5578 
5579  protected LSL_Vector GetTextureOffset(SceneObjectPart part, int face)
5580  {
5581  Primitive.TextureEntry tex = part.Shape.Textures;
5582  LSL_Vector offset = new LSL_Vector();
5583  if (face == ScriptBaseClass.ALL_SIDES)
5584  {
5585  face = 0;
5586  }
5587  if (face >= 0 && face < GetNumberOfSides(part))
5588  {
5589  offset.x = tex.GetFace((uint)face).OffsetU;
5590  offset.y = tex.GetFace((uint)face).OffsetV;
5591  offset.z = 0.0;
5592  return offset;
5593  }
5594  else
5595  {
5596  return offset;
5597  }
5598  }
5599 
5601  {
5602  m_host.AddScriptLPS(1);
5603  Primitive.TextureEntry tex = m_host.Shape.Textures;
5604  LSL_Vector scale;
5605  if (side == -1)
5606  {
5607  side = 0;
5608  }
5609  scale.x = tex.GetFace((uint)side).RepeatU;
5610  scale.y = tex.GetFace((uint)side).RepeatV;
5611  scale.z = 0.0;
5612  return scale;
5613  }
5614 
5615  public LSL_Float llGetTextureRot(int face)
5616  {
5617  m_host.AddScriptLPS(1);
5618  return GetTextureRot(m_host, face);
5619  }
5620 
5621  protected LSL_Float GetTextureRot(SceneObjectPart part, int face)
5622  {
5623  Primitive.TextureEntry tex = part.Shape.Textures;
5624  if (face == -1)
5625  {
5626  face = 0;
5627  }
5628  if (face >= 0 && face < GetNumberOfSides(part))
5629  {
5630  return tex.GetFace((uint)face).Rotation;
5631  }
5632  else
5633  {
5634  return 0.0;
5635  }
5636  }
5637 
5638  public LSL_Integer llSubStringIndex(string source, string pattern)
5639  {
5640  m_host.AddScriptLPS(1);
5641  return source.IndexOf(pattern);
5642  }
5643 
5644  public LSL_String llGetOwnerKey(string id)
5645  {
5646  m_host.AddScriptLPS(1);
5647  UUID key = new UUID();
5648  if (UUID.TryParse(id, out key))
5649  {
5650  try
5651  {
5652  SceneObjectPart obj = World.GetSceneObjectPart(key);
5653  if (obj == null)
5654  return id; // the key is for an agent so just return the key
5655  else
5656  return obj.OwnerID.ToString();
5657  }
5658  catch (KeyNotFoundException)
5659  {
5660  return id; // The Object/Agent not in the region so just return the key
5661  }
5662  }
5663  else
5664  {
5665  return UUID.Zero.ToString();
5666  }
5667  }
5668 
5670  {
5671  m_host.AddScriptLPS(1);
5672 
5673  return new LSL_Vector(m_host.GetCenterOfMass());
5674  }
5675 
5676  public LSL_List llListSort(LSL_List src, int stride, int ascending)
5677  {
5678  m_host.AddScriptLPS(1);
5679 
5680  if (stride <= 0)
5681  {
5682  stride = 1;
5683  }
5684  return src.Sort(stride, ascending);
5685  }
5686 
5688  {
5689  m_host.AddScriptLPS(1);
5690 
5691  return src.Length;
5692  }
5693 
5694  public LSL_Integer llList2Integer(LSL_List src, int index)
5695  {
5696  m_host.AddScriptLPS(1);
5697  if (index < 0)
5698  {
5699  index = src.Length + index;
5700  }
5701  if (index >= src.Length || index < 0)
5702  {
5703  return 0;
5704  }
5705 
5706  // Vectors & Rotations always return zero in SL, but
5707  // keys don't always return zero, it seems to be a bit complex.
5708  else if (src.Data[index] is LSL_Vector ||
5709  src.Data[index] is LSL_Rotation)
5710  {
5711  return 0;
5712  }
5713  try
5714  {
5715 
5716  if (src.Data[index] is LSL_Integer)
5717  return (LSL_Integer)src.Data[index];
5718  else if (src.Data[index] is LSL_Float)
5719  return Convert.ToInt32(((LSL_Float)src.Data[index]).value);
5720  return new LSL_Integer(src.Data[index].ToString());
5721  }
5722  catch (FormatException)
5723  {
5724  return 0;
5725  }
5726  }
5727 
5728  public LSL_Float llList2Float(LSL_List src, int index)
5729  {
5730  m_host.AddScriptLPS(1);
5731  if (index < 0)
5732  {
5733  index = src.Length + index;
5734  }
5735  if (index >= src.Length || index < 0)
5736  {
5737  return 0.0;
5738  }
5739 
5740  // Vectors & Rotations always return zero in SL
5741  else if (src.Data[index] is LSL_Vector ||
5742  src.Data[index] is LSL_Rotation)
5743  {
5744  return 0;
5745  }
5746  // valid keys seem to get parsed as integers then converted to floats
5747  else
5748  {
5749  UUID uuidt;
5750  if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt))
5751  {
5752  return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value);
5753  }
5754  }
5755  try
5756  {
5757  if (src.Data[index] is LSL_Integer)
5758  return Convert.ToDouble(((LSL_Integer)src.Data[index]).value);
5759  else if (src.Data[index] is LSL_Float)
5760  return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
5761  else if (src.Data[index] is LSL_String)
5762  {
5763  string str = ((LSL_String) src.Data[index]).m_string;
5764  Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5765  if (m != Match.Empty)
5766  {
5767  str = m.Value;
5768  double d = 0.0;
5769  if (!Double.TryParse(str, out d))
5770  return 0.0;
5771 
5772  return d;
5773  }
5774  return 0.0;
5775  }
5776  return Convert.ToDouble(src.Data[index]);
5777  }
5778  catch (FormatException)
5779  {
5780  return 0.0;
5781  }
5782  }
5783 
5784  public LSL_String llList2String(LSL_List src, int index)
5785  {
5786  m_host.AddScriptLPS(1);
5787  if (index < 0)
5788  {
5789  index = src.Length + index;
5790  }
5791  if (index >= src.Length || index < 0)
5792  {
5793  return String.Empty;
5794  }
5795  return src.Data[index].ToString();
5796  }
5797 
5798  public LSL_Key llList2Key(LSL_List src, int index)
5799  {
5800  m_host.AddScriptLPS(1);
5801  if (index < 0)
5802  {
5803  index = src.Length + index;
5804  }
5805 
5806  if (index >= src.Length || index < 0)
5807  {
5808  return "";
5809  }
5810 
5811  // SL spits out an empty string for types other than key & string
5812  // At the time of patching, LSL_Key is currently LSL_String,
5813  // so the OR check may be a little redundant, but it's being done
5814  // for completion and should LSL_Key ever be implemented
5815  // as it's own struct
5816  // NOTE: 3rd case is needed because a NULL_KEY comes through as
5817  // type 'obj' and wrongly returns ""
5818  else if (!(src.Data[index] is LSL_String ||
5819  src.Data[index] is LSL_Key ||
5820  src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000"))
5821  {
5822  return "";
5823  }
5824 
5825  return src.Data[index].ToString();
5826  }
5827 
5828  public LSL_Vector llList2Vector(LSL_List src, int index)
5829  {
5830  m_host.AddScriptLPS(1);
5831  if (index < 0)
5832  {
5833  index = src.Length + index;
5834  }
5835  if (index >= src.Length || index < 0)
5836  {
5837  return new LSL_Vector(0, 0, 0);
5838  }
5839  if (src.Data[index].GetType() == typeof(LSL_Vector))
5840  {
5841  return (LSL_Vector)src.Data[index];
5842  }
5843 
5844  // SL spits always out ZERO_VECTOR for anything other than
5845  // strings or vectors. Although keys always return ZERO_VECTOR,
5846  // it is currently difficult to make the distinction between
5847  // a string, a key as string and a string that by coincidence
5848  // is a string, so we're going to leave that up to the
5849  // LSL_Vector constructor.
5850  else if (!(src.Data[index] is LSL_String ||
5851  src.Data[index] is LSL_Vector))
5852  {
5853  return new LSL_Vector(0, 0, 0);
5854  }
5855  else
5856  {
5857  return new LSL_Vector(src.Data[index].ToString());
5858  }
5859  }
5860 
5861  public LSL_Rotation llList2Rot(LSL_List src, int index)
5862  {
5863  m_host.AddScriptLPS(1);
5864  if (index < 0)
5865  {
5866  index = src.Length + index;
5867  }
5868  if (index >= src.Length || index < 0)
5869  {
5870  return new LSL_Rotation(0, 0, 0, 1);
5871  }
5872 
5873  // SL spits always out ZERO_ROTATION for anything other than
5874  // strings or vectors. Although keys always return ZERO_ROTATION,
5875  // it is currently difficult to make the distinction between
5876  // a string, a key as string and a string that by coincidence
5877  // is a string, so we're going to leave that up to the
5878  // LSL_Rotation constructor.
5879  else if (!(src.Data[index] is LSL_String ||
5880  src.Data[index] is LSL_Rotation))
5881  {
5882  return new LSL_Rotation(0, 0, 0, 1);
5883  }
5884  else if (src.Data[index].GetType() == typeof(LSL_Rotation))
5885  {
5886  return (LSL_Rotation)src.Data[index];
5887  }
5888  else
5889  {
5890  return new LSL_Rotation(src.Data[index].ToString());
5891  }
5892  }
5893 
5894  public LSL_List llList2List(LSL_List src, int start, int end)
5895  {
5896  m_host.AddScriptLPS(1);
5897  return src.GetSublist(start, end);
5898  }
5899 
5900  public LSL_List llDeleteSubList(LSL_List src, int start, int end)
5901  {
5902  return src.DeleteSublist(start, end);
5903  }
5904 
5905  public LSL_Integer llGetListEntryType(LSL_List src, int index)
5906  {
5907  m_host.AddScriptLPS(1);
5908  if (index < 0)
5909  {
5910  index = src.Length + index;
5911  }
5912  if (index >= src.Length)
5913  {
5914  return 0;
5915  }
5916 
5917  if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
5918  return 1;
5919  if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
5920  return 2;
5921  if (src.Data[index] is LSL_String || src.Data[index] is String)
5922  {
5923  UUID tuuid;
5924  if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
5925  {
5926  return 4;
5927  }
5928  else
5929  {
5930  return 3;
5931  }
5932  }
5933  if (src.Data[index] is LSL_Vector)
5934  return 5;
5935  if (src.Data[index] is LSL_Rotation)
5936  return 6;
5937  if (src.Data[index] is LSL_List)
5938  return 7;
5939  return 0;
5940 
5941  }
5942 
5950  {
5951  m_host.AddScriptLPS(1);
5952 
5953  return string.Join(", ",
5954  (new List<object>(src.Data)).ConvertAll<string>(o =>
5955  {
5956  return o.ToString();
5957  }).ToArray());
5958  }
5959 
5967 
5968  public LSL_List llCSV2List(string src)
5969  {
5970 
5971  LSL_List result = new LSL_List();
5972  int parens = 0;
5973  int start = 0;
5974  int length = 0;
5975 
5976  m_host.AddScriptLPS(1);
5977 
5978  for (int i = 0; i < src.Length; i++)
5979  {
5980  switch (src[i])
5981  {
5982  case '<':
5983  parens++;
5984  length++;
5985  break;
5986  case '>':
5987  if (parens > 0)
5988  parens--;
5989  length++;
5990  break;
5991  case ',':
5992  if (parens == 0)
5993  {
5994  result.Add(new LSL_String(src.Substring(start,length).Trim()));
5995  start += length+1;
5996  length = 0;
5997  }
5998  else
5999  {
6000  length++;
6001  }
6002  break;
6003  default:
6004  length++;
6005  break;
6006  }
6007  }
6008 
6009  result.Add(new LSL_String(src.Substring(start,length).Trim()));
6010 
6011  return result;
6012  }
6013 
6024 
6025  public LSL_List llListRandomize(LSL_List src, int stride)
6026  {
6027  LSL_List result;
6028  BetterRandom rand = new BetterRandom();
6029 
6030  int chunkk;
6031  int[] chunks;
6032 
6033  m_host.AddScriptLPS(1);
6034 
6035  if (stride <= 0)
6036  {
6037  stride = 1;
6038  }
6039 
6040  // Stride MUST be a factor of the list length
6041  // If not, then return the src list. This also
6042  // traps those cases where stride > length.
6043 
6044  if (src.Length != stride && src.Length % stride == 0)
6045  {
6046  chunkk = src.Length/stride;
6047 
6048  chunks = new int[chunkk];
6049 
6050  for (int i = 0; i < chunkk; i++)
6051  {
6052  chunks[i] = i;
6053  }
6054 
6055  // Knuth shuffle the chunkk index
6056  for (int i = chunkk - 1; i > 0; i--)
6057  {
6058  // Elect an unrandomized chunk to swap
6059  int index = rand.Next(i + 1);
6060 
6061  // and swap position with first unrandomized chunk
6062  int tmp = chunks[i];
6063  chunks[i] = chunks[index];
6064  chunks[index] = tmp;
6065  }
6066 
6067  // Construct the randomized list
6068 
6069  result = new LSL_List();
6070 
6071  for (int i = 0; i < chunkk; i++)
6072  {
6073  for (int j = 0; j < stride; j++)
6074  {
6075  result.Add(src.Data[chunks[i] * stride + j]);
6076  }
6077  }
6078  }
6079  else
6080  {
6081  object[] array = new object[src.Length];
6082  Array.Copy(src.Data, 0, array, 0, src.Length);
6083  result = new LSL_List(array);
6084  }
6085 
6086  return result;
6087  }
6088 
6096 
6097  public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
6098  {
6099 
6100  LSL_List result = new LSL_List();
6101  int[] si = new int[2];
6102  int[] ei = new int[2];
6103  bool twopass = false;
6104 
6105  m_host.AddScriptLPS(1);
6106 
6107  // First step is always to deal with negative indices
6108 
6109  if (start < 0)
6110  start = src.Length+start;
6111  if (end < 0)
6112  end = src.Length+end;
6113 
6114  // Out of bounds indices are OK, just trim them
6115  // accordingly
6116 
6117  if (start > src.Length)
6118  start = src.Length;
6119 
6120  if (end > src.Length)
6121  end = src.Length;
6122 
6123  if (stride == 0)
6124  stride = 1;
6125 
6126  // There may be one or two ranges to be considered
6127 
6128  if (start != end)
6129  {
6130 
6131  if (start <= end)
6132  {
6133  si[0] = start;
6134  ei[0] = end;
6135  }
6136  else
6137  {
6138  si[1] = start;
6139  ei[1] = src.Length;
6140  si[0] = 0;
6141  ei[0] = end;
6142  twopass = true;
6143  }
6144 
6145  // The scan always starts from the beginning of the
6146  // source list, but members are only selected if they
6147  // fall within the specified sub-range. The specified
6148  // range values are inclusive.
6149  // A negative stride reverses the direction of the
6150  // scan producing an inverted list as a result.
6151 
6152  if (stride > 0)
6153  {
6154  for (int i = 0; i < src.Length; i += stride)
6155  {
6156  if (i<=ei[0] && i>=si[0])
6157  result.Add(src.Data[i]);
6158  if (twopass && i>=si[1] && i<=ei[1])
6159  result.Add(src.Data[i]);
6160  }
6161  }
6162  else if (stride < 0)
6163  {
6164  for (int i = src.Length - 1; i >= 0; i += stride)
6165  {
6166  if (i <= ei[0] && i >= si[0])
6167  result.Add(src.Data[i]);
6168  if (twopass && i >= si[1] && i <= ei[1])
6169  result.Add(src.Data[i]);
6170  }
6171  }
6172  }
6173  else
6174  {
6175  if (start%stride == 0)
6176  {
6177  result.Add(src.Data[start]);
6178  }
6179  }
6180 
6181  return result;
6182  }
6183 
6185  {
6186  m_host.AddScriptLPS(1);
6187 
6188  int count = 0;
6189  World.ForEachRootScenePresence(delegate(ScenePresence sp) {
6190  count++;
6191  });
6192 
6193  return new LSL_Integer(count);
6194  }
6195 
6197  {
6198  m_host.AddScriptLPS(1);
6199  return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
6200  }
6201 
6203  {
6204  m_host.AddScriptLPS(1);
6205  if (name == "agent_limit")
6206  {
6207  return World.RegionInfo.RegionSettings.AgentLimit.ToString();
6208  }
6209  else if (name == "dynamic_pathfinding")
6210  {
6211  return "0";
6212  }
6213  else if (name == "estate_id")
6214  {
6215  return World.RegionInfo.EstateSettings.EstateID.ToString();
6216  }
6217  else if (name == "estate_name")
6218  {
6219  return World.RegionInfo.EstateSettings.EstateName;
6220  }
6221  else if (name == "frame_number")
6222  {
6223  return World.Frame.ToString();
6224  }
6225  else if (name == "region_cpu_ratio")
6226  {
6227  return "1";
6228  }
6229  else if (name == "region_idle")
6230  {
6231  return "0";
6232  }
6233  else if (name == "region_product_name")
6234  {
6235  if (World.RegionInfo.RegionType != String.Empty)
6236  return World.RegionInfo.RegionType;
6237  else
6238  return "";
6239  }
6240  else if (name == "region_product_sku")
6241  {
6242  return "OpenSim";
6243  }
6244  else if (name == "region_start_time")
6245  {
6246  return World.UnixStartTime.ToString();
6247  }
6248  else if (name == "sim_channel")
6249  {
6250  return "OpenSim";
6251  }
6252  else if (name == "sim_version")
6253  {
6254  return World.GetSimulatorVersion();
6255  }
6256  else if (name == "simulator_hostname")
6257  {
6258  IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
6259  return UrlModule.ExternalHostNameForLSL;
6260  }
6261  else
6262  {
6263  return "";
6264  }
6265 
6266  }
6267 
6273 
6274  public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
6275  {
6276 
6277  LSL_List pref;
6278  LSL_List suff;
6279 
6280  m_host.AddScriptLPS(1);
6281 
6282  if (index < 0)
6283  {
6284  index = index+dest.Length;
6285  if (index < 0)
6286  {
6287  index = 0;
6288  }
6289  }
6290 
6291  if (index != 0)
6292  {
6293  pref = dest.GetSublist(0,index-1);
6294  if (index < dest.Length)
6295  {
6296  suff = dest.GetSublist(index,-1);
6297  return pref + src + suff;
6298  }
6299  else
6300  {
6301  return pref + src;
6302  }
6303  }
6304  else
6305  {
6306  if (index < dest.Length)
6307  {
6308  suff = dest.GetSublist(index,-1);
6309  return src + suff;
6310  }
6311  else
6312  {
6313  return src;
6314  }
6315  }
6316 
6317  }
6318 
6330  {
6331  int index = -1;
6332  int length = src.Length - test.Length + 1;
6333 
6334  m_host.AddScriptLPS(1);
6335 
6336  // If either list is empty, do not match
6337  if (src.Length != 0 && test.Length != 0)
6338  {
6339  for (int i = 0; i < length; i++)
6340  {
6341  int needle = llGetListEntryType(test, 0).value;
6342  int haystack = llGetListEntryType(src, i).value;
6343 
6344  // Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
6345  // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
6346  // and so the comparison fails even if the LSL_Integer conceptually has the same value.
6347  // Therefore, here we test Equals on both the source and destination objects.
6348  // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
6349  if ((needle == haystack) && (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])))
6350  {
6351  int j;
6352  for (j = 1; j < test.Length; j++)
6353  {
6354  needle = llGetListEntryType(test, j).value;
6355  haystack = llGetListEntryType(src, i+j).value;
6356 
6357  if ((needle != haystack) || (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))))
6358  break;
6359  }
6360 
6361  if (j == test.Length)
6362  {
6363  index = i;
6364  break;
6365  }
6366  }
6367  }
6368  }
6369 
6370  return index;
6371  }
6372 
6374  {
6375  m_host.AddScriptLPS(1);
6376  return m_host.Name !=null ? m_host.Name : String.Empty;
6377  }
6378 
6379  public void llSetObjectName(string name)
6380  {
6381  m_host.AddScriptLPS(1);
6382  m_host.Name = name != null ? name : String.Empty;
6383  }
6384 
6386  {
6387  m_host.AddScriptLPS(1);
6388  DateTime date = DateTime.Now.ToUniversalTime();
6389  string result = date.ToString("yyyy-MM-dd");
6390  return result;
6391  }
6392 
6394  {
6395  m_host.AddScriptLPS(1);
6396 
6397  // edge will be used to pass the Region Coordinates offset
6398  // we want to check for a neighboring sim
6399  LSL_Vector edge = new LSL_Vector(0, 0, 0);
6400 
6401  if (dir.x == 0)
6402  {
6403  if (dir.y == 0)
6404  {
6405  // Direction vector is 0,0 so return
6406  // false since we're staying in the sim
6407  return 0;
6408  }
6409  else
6410  {
6411  // Y is the only valid direction
6412  edge.y = dir.y / Math.Abs(dir.y);
6413  }
6414  }
6415  else
6416  {
6417  LSL_Float mag;
6418  if (dir.x > 0)
6419  {
6420  mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
6421  }
6422  else
6423  {
6424  mag = (pos.x/dir.x);
6425  }
6426 
6427  mag = Math.Abs(mag);
6428 
6429  edge.y = pos.y + (dir.y * mag);
6430 
6431  if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
6432  {
6433  // Y goes out of bounds first
6434  edge.y = dir.y / Math.Abs(dir.y);
6435  }
6436  else
6437  {
6438  // X goes out of bounds first or its a corner exit
6439  edge.y = 0;
6440  edge.x = dir.x / Math.Abs(dir.x);
6441  }
6442  }
6443 
6444  List<GridRegion> neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID);
6445 
6446  uint neighborX = World.RegionInfo.RegionLocX + (uint)dir.x;
6447  uint neighborY = World.RegionInfo.RegionLocY + (uint)dir.y;
6448 
6449  foreach (GridRegion sri in neighbors)
6450  {
6451  if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY)
6452  return 0;
6453  }
6454 
6455  return 1;
6456  }
6457 
6463  public LSL_Integer llGetAgentInfo(string id)
6464  {
6465  m_host.AddScriptLPS(1);
6466 
6467  UUID key = new UUID();
6468  if (!UUID.TryParse(id, out key))
6469  {
6470  return 0;
6471  }
6472 
6473  int flags = 0;
6474 
6475  ScenePresence agent = World.GetScenePresence(key);
6476  if (agent == null)
6477  {
6478  return 0;
6479  }
6480 
6481  if (agent.IsChildAgent)
6482  return 0; // Fail if they are not in the same region
6483 
6484  // note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL
6485  if (agent.SetAlwaysRun)
6486  {
6487  flags |= ScriptBaseClass.AGENT_ALWAYS_RUN;
6488  }
6489 
6490  if (agent.HasAttachments())
6491  {
6492  flags |= ScriptBaseClass.AGENT_ATTACHMENTS;
6493  if (agent.HasScriptedAttachments())
6495  }
6496 
6497  if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
6498  {
6499  flags |= ScriptBaseClass.AGENT_FLYING;
6500  flags |= ScriptBaseClass.AGENT_IN_AIR; // flying always implies in-air, even if colliding with e.g. a wall
6501  }
6502 
6503  if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0)
6504  {
6505  flags |= ScriptBaseClass.AGENT_AWAY;
6506  }
6507 
6508  UUID busy = new UUID("efcf670c-2d18-8128-973a-034ebc806b67");
6509  UUID[] anims = agent.Animator.GetAnimationArray();
6510  if (Array.Exists<UUID>(anims, a => { return a == busy; }))
6511  {
6512  flags |= ScriptBaseClass.AGENT_BUSY;
6513  }
6514 
6515  // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
6516  if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
6517  {
6518  flags |= ScriptBaseClass.AGENT_MOUSELOOK;
6519  }
6520 
6521  if ((agent.State & (byte)AgentState.Typing) != (byte)0)
6522  {
6523  flags |= ScriptBaseClass.AGENT_TYPING;
6524  }
6525 
6526  string agentMovementAnimation = agent.Animator.CurrentMovementAnimation;
6527 
6528  if (agentMovementAnimation == "CROUCH")
6529  {
6530  flags |= ScriptBaseClass.AGENT_CROUCHING;
6531  }
6532 
6533  if (agentMovementAnimation == "WALK" || agentMovementAnimation == "CROUCHWALK")
6534  {
6535  flags |= ScriptBaseClass.AGENT_WALKING;
6536  }
6537 
6538  // not colliding implies in air. Note: flying also implies in-air, even if colliding (see above)
6539 
6540  // note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL.
6541 
6542  // note: this may need some tweaking when walking downhill. you "fall down" for a brief instant
6543  // and don't collide when walking downhill, which instantly registers as in-air, briefly. should
6544  // there be some minimum non-collision threshold time before claiming the avatar is in-air?
6545  if ((flags & ScriptBaseClass.AGENT_WALKING) == 0 && !agent.IsColliding )
6546  {
6547  flags |= ScriptBaseClass.AGENT_IN_AIR;
6548  }
6549 
6550  if (agent.ParentPart != null)
6551  {
6552  flags |= ScriptBaseClass.AGENT_ON_OBJECT;
6553  flags |= ScriptBaseClass.AGENT_SITTING;
6554  }
6555 
6556  if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID
6557  == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
6558  {
6559  flags |= ScriptBaseClass.AGENT_SITTING;
6560  }
6561 
6562  if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6563  {
6564  flags |= ScriptBaseClass.AGENT_MALE;
6565  }
6566 
6567  return flags;
6568  }
6569 
6570  public LSL_String llGetAgentLanguage(string id)
6571  {
6572  // This should only return a value if the avatar is in the same region, but eh. idc.
6573  m_host.AddScriptLPS(1);
6574  if (World.AgentPreferencesService == null)
6575  {
6576  Error("llGetAgentLanguage", "No AgentPreferencesService present");
6577  }
6578  else
6579  {
6580  UUID key = new UUID();
6581  if (UUID.TryParse(id, out key))
6582  {
6583  return new LSL_String(World.AgentPreferencesService.GetLang(key));
6584  }
6585  }
6586  return new LSL_String("en-us");
6587  }
6598  {
6599  m_host.AddScriptLPS(1);
6600 
6601  // the constants are 1, 2 and 4 so bits are being set, but you
6602  // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4
6603  bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION;
6604  bool parcelOwned = scope == ScriptBaseClass.AGENT_LIST_PARCEL_OWNER;
6605  bool parcel = scope == ScriptBaseClass.AGENT_LIST_PARCEL;
6606 
6607  LSL_List result = new LSL_List();
6608 
6609  if (!regionWide && !parcelOwned && !parcel)
6610  {
6611  result.Add("INVALID_SCOPE");
6612  return result;
6613  }
6614 
6615  ILandObject land;
6616  UUID id = UUID.Zero;
6617 
6618  if (parcel || parcelOwned)
6619  {
6620  land = World.LandChannel.GetLandObject(m_host.ParentGroup.RootPart.GetWorldPosition());
6621  if (land == null)
6622  {
6623  id = UUID.Zero;
6624  }
6625  else
6626  {
6627  if (parcelOwned)
6628  {
6629  id = land.LandData.OwnerID;
6630  }
6631  else
6632  {
6633  id = land.LandData.GlobalID;
6634  }
6635  }
6636  }
6637 
6638  World.ForEachRootScenePresence(
6639  delegate (ScenePresence ssp)
6640  {
6641  // Gods are not listed in SL
6642  if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent)
6643  {
6644  if (!regionWide)
6645  {
6646  land = World.LandChannel.GetLandObject(ssp.AbsolutePosition);
6647  if (land != null)
6648  {
6649  if (parcelOwned && land.LandData.OwnerID == id ||
6650  parcel && land.LandData.GlobalID == id)
6651  {
6652  result.Add(new LSL_Key(ssp.UUID.ToString()));
6653  }
6654  }
6655  }
6656  else
6657  {
6658  result.Add(new LSL_Key(ssp.UUID.ToString()));
6659  }
6660  }
6661  // Maximum of 100 results
6662  if (result.Length > 99)
6663  {
6664  return;
6665  }
6666  }
6667  );
6668  return result;
6669  }
6670 
6671  public void llAdjustSoundVolume(double volume)
6672  {
6673  m_host.AddScriptLPS(1);
6674  m_host.AdjustSoundGain(volume);
6675  ScriptSleep(m_sleepMsOnAdjustSoundVolume);
6676  }
6677 
6678  public void llSetSoundRadius(double radius)
6679  {
6680  m_host.AddScriptLPS(1);
6681  m_host.SoundRadius = radius;
6682  }
6683 
6684  public LSL_String llKey2Name(string id)
6685  {
6686  m_host.AddScriptLPS(1);
6687  UUID key = new UUID();
6688  if (UUID.TryParse(id,out key))
6689  {
6690  ScenePresence presence = World.GetScenePresence(key);
6691 
6692  if (presence != null)
6693  {
6694  return presence.ControllingClient.Name;
6695  //return presence.Name;
6696  }
6697 
6698  if (World.GetSceneObjectPart(key) != null)
6699  {
6700  return World.GetSceneObjectPart(key).Name;
6701  }
6702  }
6703  return String.Empty;
6704  }
6705 
6706 
6707 
6708  public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
6709  {
6710  m_host.AddScriptLPS(1);
6711 
6712  SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate);
6713  }
6714 
6715  public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate)
6716  {
6717  m_host.AddScriptLPS(1);
6718 
6719  List<SceneObjectPart> parts = GetLinkParts(linknumber);
6720 
6721  try
6722  {
6723  foreach (SceneObjectPart part in parts)
6724  {
6725  SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6726  }
6727  }
6728  finally
6729  {
6730  }
6731  }
6732 
6733  private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
6734  {
6735 
6736  Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
6737  pTexAnim.Flags = (Primitive.TextureAnimMode)mode;
6738 
6739  //ALL_SIDES
6740  if (face == ScriptBaseClass.ALL_SIDES)
6741  face = 255;
6742 
6743  pTexAnim.Face = (uint)face;
6744  pTexAnim.Length = (float)length;
6745  pTexAnim.Rate = (float)rate;
6746  pTexAnim.SizeX = (uint)sizex;
6747  pTexAnim.SizeY = (uint)sizey;
6748  pTexAnim.Start = (float)start;
6749 
6750  part.AddTextureAnimation(pTexAnim);
6751  part.SendFullUpdateToAllClients();
6752  part.ParentGroup.HasGroupChanged = true;
6753  }
6754 
6755  public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
6756  LSL_Vector bottom_south_west)
6757  {
6758  m_host.AddScriptLPS(1);
6759  if (m_SoundModule != null)
6760  {
6761  m_SoundModule.TriggerSoundLimited(m_host.UUID,
6762  ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume,
6763  bottom_south_west, top_north_east);
6764  }
6765  }
6766 
6767  public void llEjectFromLand(string pest)
6768  {
6769  m_host.AddScriptLPS(1);
6770  UUID agentID = new UUID();
6771  if (UUID.TryParse(pest, out agentID))
6772  {
6773  ScenePresence presence = World.GetScenePresence(agentID);
6774  if (presence != null)
6775  {
6776  // agent must be over the owners land
6777  ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition);
6778  if (land == null)
6779  return;
6780 
6781  if (m_host.OwnerID == land.LandData.OwnerID)
6782  {
6783  Vector3 p = World.GetNearestAllowedPosition(presence, land);
6784  presence.TeleportWithMomentum(p, null);
6785  presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
6786  }
6787  }
6788  }
6789  ScriptSleep(m_sleepMsOnEjectFromLand);
6790  }
6791 
6792  public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6793  {
6794  return ParseString2List(str, separators, in_spacers, false);
6795  }
6796 
6797  public LSL_Integer llOverMyLand(string id)
6798  {
6799  m_host.AddScriptLPS(1);
6800  UUID key = new UUID();
6801  if (UUID.TryParse(id, out key))
6802  {
6803  ScenePresence presence = World.GetScenePresence(key);
6804  if (presence != null) // object is an avatar
6805  {
6806  if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
6807  return 1;
6808  }
6809  else // object is not an avatar
6810  {
6811  SceneObjectPart obj = World.GetSceneObjectPart(key);
6812 
6813  if (obj != null)
6814  {
6815  if (m_host.OwnerID == World.LandChannel.GetLandObject(obj.AbsolutePosition).LandData.OwnerID)
6816  return 1;
6817  }
6818  }
6819  }
6820 
6821  return 0;
6822  }
6823 
6825  {
6826  m_host.AddScriptLPS(1);
6827  ILandObject land = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
6828  if (land == null)
6829  return UUID.Zero.ToString();
6830  return land.LandData.OwnerID.ToString();
6831  }
6832 
6838  public LSL_Vector llGetAgentSize(string id)
6839  {
6840  m_host.AddScriptLPS(1);
6841  ScenePresence avatar = World.GetScenePresence((UUID)id);
6842  LSL_Vector agentSize;
6843  if (avatar == null || avatar.IsChildAgent) // Fail if not in the same region
6844  {
6845  agentSize = ScriptBaseClass.ZERO_VECTOR;
6846  }
6847  else
6848  {
6849 // agentSize = new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight);
6850  Vector3 s = avatar.Appearance.AvatarSize;
6851  agentSize = new LSL_Vector(s.X, s.Y, s.Z);
6852  }
6853  return agentSize;
6854  }
6855 
6856  public LSL_Integer llSameGroup(string id)
6857  {
6858  m_host.AddScriptLPS(1);
6859  UUID uuid = new UUID();
6860  if (!UUID.TryParse(id, out uuid))
6861  return new LSL_Integer(0);
6862 
6863  // Check if it's a group key
6864  if (uuid == m_host.ParentGroup.RootPart.GroupID)
6865  return new LSL_Integer(1);
6866 
6867  // We got passed a UUID.Zero
6868  if (uuid == UUID.Zero)
6869  return new LSL_Integer(0);
6870 
6871  // Handle the case where id names an avatar
6872  ScenePresence presence = World.GetScenePresence(uuid);
6873  if (presence != null)
6874  {
6875  if (presence.IsChildAgent)
6876  return new LSL_Integer(0);
6877 
6878  IClientAPI client = presence.ControllingClient;
6879  if (m_host.ParentGroup.RootPart.GroupID == client.ActiveGroupId)
6880  return new LSL_Integer(1);
6881 
6882  return new LSL_Integer(0);
6883  }
6884 
6885  // Handle object case
6886  SceneObjectPart part = World.GetSceneObjectPart(uuid);
6887  if (part != null)
6888  {
6889  // This will handle both deed and non-deed and also the no
6890  // group case
6891  if (part.ParentGroup.RootPart.GroupID == m_host.ParentGroup.RootPart.GroupID)
6892  return new LSL_Integer(1);
6893 
6894  return new LSL_Integer(0);
6895  }
6896 
6897  return new LSL_Integer(0);
6898  }
6899 
6900  public void llUnSit(string id)
6901  {
6902  m_host.AddScriptLPS(1);
6903 
6904  UUID key = new UUID();
6905  if (UUID.TryParse(id, out key))
6906  {
6907  ScenePresence av = World.GetScenePresence(key);
6908  List<ScenePresence> sittingAvatars = m_host.ParentGroup.GetSittingAvatars();
6909 
6910  if (av != null)
6911  {
6912  if (sittingAvatars.Contains(av))
6913  {
6914  // if the avatar is sitting on this object, then
6915  // we can unsit them. We don't want random scripts unsitting random people
6916  // Lets avoid the popcorn avatar scenario.
6917  av.StandUp();
6918  }
6919  else
6920  {
6921  // If the object owner also owns the parcel
6922  // or
6923  // if the land is group owned and the object is group owned by the same group
6924  // or
6925  // if the object is owned by a person with estate access.
6926  ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition);
6927  if (parcel != null)
6928  {
6929  if (m_host.OwnerID == parcel.LandData.OwnerID ||
6930  (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID
6931  && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID))
6932  {
6933  av.StandUp();
6934  }
6935  }
6936  }
6937  }
6938  }
6939  }
6940 
6942  {
6943  m_host.AddScriptLPS(1);
6944 
6945  //Get the slope normal. This gives us the equation of the plane tangent to the slope.
6946  LSL_Vector vsn = llGroundNormal(offset);
6947 
6948  //Plug the x,y coordinates of the slope normal into the equation of the plane to get
6949  //the height of that point on the plane. The resulting vector gives the slope.
6950  Vector3 vsl = vsn;
6951  vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z));
6952  vsl.Normalize();
6953  //Normalization might be overkill here
6954 
6955  vsn.x = vsl.X;
6956  vsn.y = vsl.Y;
6957  vsn.z = vsl.Z;
6958 
6959  return vsn;
6960  }
6961 
6963  {
6964  m_host.AddScriptLPS(1);
6965  Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
6966  // Clamp to valid position
6967  if (pos.X < 0)
6968  pos.X = 0;
6969  else if (pos.X >= World.Heightmap.Width)
6970  pos.X = World.Heightmap.Width - 1;
6971  if (pos.Y < 0)
6972  pos.Y = 0;
6973  else if (pos.Y >= World.Heightmap.Height)
6974  pos.Y = World.Heightmap.Height - 1;
6975 
6976  //Find two points in addition to the position to define a plane
6977  Vector3 p0 = new Vector3(pos.X, pos.Y,
6978  (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
6979  Vector3 p1 = new Vector3();
6980  Vector3 p2 = new Vector3();
6981  if ((pos.X + 1.0f) >= World.Heightmap.Width)
6982  p1 = new Vector3(pos.X + 1.0f, pos.Y,
6983  (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
6984  else
6985  p1 = new Vector3(pos.X + 1.0f, pos.Y,
6986  (float)World.Heightmap[(int)(pos.X + 1.0f), (int)pos.Y]);
6987  if ((pos.Y + 1.0f) >= World.Heightmap.Height)
6988  p2 = new Vector3(pos.X, pos.Y + 1.0f,
6989  (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
6990  else
6991  p2 = new Vector3(pos.X, pos.Y + 1.0f,
6992  (float)World.Heightmap[(int)pos.X, (int)(pos.Y + 1.0f)]);
6993 
6994  //Find normalized vectors from p0 to p1 and p0 to p2
6995  Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
6996  Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z);
6997  v0.Normalize();
6998  v1.Normalize();
6999 
7000  //Find the cross product of the vectors (the slope normal).
7001  Vector3 vsn = new Vector3();
7002  vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y);
7003  vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z);
7004  vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X);
7005  vsn.Normalize();
7006  //I believe the crossproduct of two normalized vectors is a normalized vector so
7007  //this normalization may be overkill
7008 
7009  return new LSL_Vector(vsn);
7010  }
7011 
7013  {
7014  m_host.AddScriptLPS(1);
7015  LSL_Vector x = llGroundSlope(offset);
7016  return new LSL_Vector(-x.y, x.x, 0.0);
7017  }
7018 
7020  {
7021  m_host.AddScriptLPS(1);
7022  return m_host.ParentGroup.AttachmentPoint;
7023  }
7024 
7025  public virtual LSL_Integer llGetFreeMemory()
7026  {
7027  m_host.AddScriptLPS(1);
7028  // Make scripts designed for Mono happy
7029  return 65536;
7030  }
7031 
7033  {
7034  m_host.AddScriptLPS(1);
7035  if (m_UrlModule != null)
7036  return new LSL_Integer(m_UrlModule.GetFreeUrls());
7037  return new LSL_Integer(0);
7038  }
7039 
7040 
7042  {
7043  m_host.AddScriptLPS(1);
7044  return World.RegionInfo.RegionName;
7045  }
7046 
7048  {
7049  m_host.AddScriptLPS(1);
7050  return (double)World.TimeDilation;
7051  }
7052 
7057  {
7058  m_host.AddScriptLPS(1);
7059  return World.StatsReporter.LastReportedSimFPS;
7060  }
7061 
7062 
7063  /* particle system rules should be coming into this routine as doubles, that is
7064  rule[0] should be an integer from this list and rule[1] should be the arg
7065  for the same integer. wiki.secondlife.com has most of this mapping, but some
7066  came from http://www.caligari-designs.com/p4u2
7067 
7068  We iterate through the list for 'Count' elements, incrementing by two for each
7069  iteration and set the members of Primitive.ParticleSystem, one at a time.
7070  */
7071 
7072  public enum PrimitiveRule : int
7073  {
7074  PSYS_PART_FLAGS = 0,
7075  PSYS_PART_START_COLOR = 1,
7076  PSYS_PART_START_ALPHA = 2,
7077  PSYS_PART_END_COLOR = 3,
7078  PSYS_PART_END_ALPHA = 4,
7079  PSYS_PART_START_SCALE = 5,
7080  PSYS_PART_END_SCALE = 6,
7081  PSYS_PART_MAX_AGE = 7,
7082  PSYS_SRC_ACCEL = 8,
7083  PSYS_SRC_PATTERN = 9,
7084  PSYS_SRC_INNERANGLE = 10,
7085  PSYS_SRC_OUTERANGLE = 11,
7086  PSYS_SRC_TEXTURE = 12,
7087  PSYS_SRC_BURST_RATE = 13,
7088  PSYS_SRC_BURST_PART_COUNT = 15,
7089  PSYS_SRC_BURST_RADIUS = 16,
7090  PSYS_SRC_BURST_SPEED_MIN = 17,
7091  PSYS_SRC_BURST_SPEED_MAX = 18,
7092  PSYS_SRC_MAX_AGE = 19,
7093  PSYS_SRC_TARGET_KEY = 20,
7094  PSYS_SRC_OMEGA = 21,
7095  PSYS_SRC_ANGLE_BEGIN = 22,
7096  PSYS_SRC_ANGLE_END = 23,
7097  PSYS_PART_BLEND_FUNC_SOURCE = 24,
7098  PSYS_PART_BLEND_FUNC_DEST = 25,
7099  PSYS_PART_START_GLOW = 26,
7100  PSYS_PART_END_GLOW = 27
7101  }
7102 
7103  internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
7104  {
7105  Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
7106 
7107  return returnval;
7108  }
7109 
7110  protected Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
7111  {
7112  Primitive.ParticleSystem ps = new Primitive.ParticleSystem();
7113 
7114  // TODO find out about the other defaults and add them here
7115  ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
7116  ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
7117  ps.PartStartScaleX = 1.0f;
7118  ps.PartStartScaleY = 1.0f;
7119  ps.PartEndScaleX = 1.0f;
7120  ps.PartEndScaleY = 1.0f;
7121  ps.BurstSpeedMin = 1.0f;
7122  ps.BurstSpeedMax = 1.0f;
7123  ps.BurstRate = 0.1f;
7124  ps.PartMaxAge = 10.0f;
7125  ps.BurstPartCount = 1;
7126  ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA;
7127  ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA;
7128  ps.PartStartGlow = 0.0f;
7129  ps.PartEndGlow = 0.0f;
7130 
7131  return ps;
7132  }
7133 
7134  public void llLinkParticleSystem(int linknumber, LSL_List rules)
7135  {
7136  m_host.AddScriptLPS(1);
7137 
7138  List<SceneObjectPart> parts = GetLinkParts(linknumber);
7139 
7140  foreach (SceneObjectPart part in parts)
7141  {
7142  SetParticleSystem(part, rules, "llLinkParticleSystem");
7143  }
7144  }
7145 
7146  public void llParticleSystem(LSL_List rules)
7147  {
7148  m_host.AddScriptLPS(1);
7149  SetParticleSystem(m_host, rules, "llParticleSystem");
7150  }
7151 
7152  private void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc)
7153  {
7154  if (rules.Length == 0)
7155  {
7156  part.RemoveParticleSystem();
7157  part.ParentGroup.HasGroupChanged = true;
7158  }
7159  else
7160  {
7161  Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
7162  LSL_Vector tempv = new LSL_Vector();
7163 
7164  float tempf = 0;
7165  int tmpi = 0;
7166 
7167  for (int i = 0; i < rules.Length; i += 2)
7168  {
7169  int psystype;
7170  try
7171  {
7172  psystype = rules.GetLSLIntegerItem(i);
7173  }
7174  catch (InvalidCastException)
7175  {
7176  Error(originFunc, string.Format("Error running particle system params index #{0}: particle system parameter type must be integer", i));
7177  return;
7178  }
7179  switch (psystype)
7180  {
7181  case (int)ScriptBaseClass.PSYS_PART_FLAGS:
7182  try
7183  {
7184  prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
7185  }
7186  catch(InvalidCastException)
7187  {
7188  Error(originFunc, string.Format("Error running rule PSYS_PART_FLAGS: arg #{0} - parameter 1 must be integer", i + 1));
7189  return;
7190  }
7191  break;
7192 
7193  case (int)ScriptBaseClass.PSYS_PART_START_COLOR:
7194  try
7195  {
7196  tempv = rules.GetVector3Item(i + 1);
7197  }
7198  catch(InvalidCastException)
7199  {
7200  Error(originFunc, string.Format("Error running rule PSYS_PART_START_COLOR: arg #{0} - parameter 1 must be vector", i + 1));
7201  return;
7202  }
7203  prules.PartStartColor.R = (float)tempv.x;
7204  prules.PartStartColor.G = (float)tempv.y;
7205  prules.PartStartColor.B = (float)tempv.z;
7206  break;
7207 
7208  case (int)ScriptBaseClass.PSYS_PART_START_ALPHA:
7209  try
7210  {
7211  tempf = (float)rules.GetLSLFloatItem(i + 1);
7212  }
7213  catch(InvalidCastException)
7214  {
7215  Error(originFunc, string.Format("Error running rule PSYS_PART_START_ALPHA: arg #{0} - parameter 1 must be float", i + 1));
7216  return;
7217  }
7218  prules.PartStartColor.A = tempf;
7219  break;
7220 
7221  case (int)ScriptBaseClass.PSYS_PART_END_COLOR:
7222  try
7223  {
7224  tempv = rules.GetVector3Item(i + 1);
7225  }
7226  catch(InvalidCastException)
7227  {
7228  Error(originFunc, string.Format("Error running rule PSYS_PART_END_COLOR: arg #{0} - parameter 1 must be vector", i + 1));
7229  return;
7230  }
7231  prules.PartEndColor.R = (float)tempv.x;
7232  prules.PartEndColor.G = (float)tempv.y;
7233  prules.PartEndColor.B = (float)tempv.z;
7234  break;
7235 
7236  case (int)ScriptBaseClass.PSYS_PART_END_ALPHA:
7237  try
7238  {
7239  tempf = (float)rules.GetLSLFloatItem(i + 1);
7240  }
7241  catch(InvalidCastException)
7242  {
7243  Error(originFunc, string.Format("Error running rule PSYS_PART_END_ALPHA: arg #{0} - parameter 1 must be float", i + 1));
7244  return;
7245  }
7246  prules.PartEndColor.A = tempf;
7247  break;
7248 
7249  case (int)ScriptBaseClass.PSYS_PART_START_SCALE:
7250  try
7251  {
7252  tempv = rules.GetVector3Item(i + 1);
7253  }
7254  catch(InvalidCastException)
7255  {
7256  Error(originFunc, string.Format("Error running rule PSYS_PART_START_SCALE: arg #{0} - parameter 1 must be vector", i + 1));
7257  return;
7258  }
7259  prules.PartStartScaleX = validParticleScale((float)tempv.x);
7260  prules.PartStartScaleY = validParticleScale((float)tempv.y);
7261  break;
7262 
7263  case (int)ScriptBaseClass.PSYS_PART_END_SCALE:
7264  try
7265  {
7266  tempv = rules.GetVector3Item(i + 1);
7267  }
7268  catch(InvalidCastException)
7269  {
7270  Error(originFunc, string.Format("Error running rule PSYS_PART_END_SCALE: arg #{0} - parameter 1 must be vector", i + 1));
7271  return;
7272  }
7273  prules.PartEndScaleX = validParticleScale((float)tempv.x);
7274  prules.PartEndScaleY = validParticleScale((float)tempv.y);
7275  break;
7276 
7277  case (int)ScriptBaseClass.PSYS_PART_MAX_AGE:
7278  try
7279  {
7280  tempf = (float)rules.GetLSLFloatItem(i + 1);
7281  }
7282  catch(InvalidCastException)
7283  {
7284  Error(originFunc, string.Format("Error running rule PSYS_PART_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1));
7285  return;
7286  }
7287  prules.PartMaxAge = tempf;
7288  break;
7289 
7290  case (int)ScriptBaseClass.PSYS_SRC_ACCEL:
7291  try
7292  {
7293  tempv = rules.GetVector3Item(i + 1);
7294  }
7295  catch(InvalidCastException)
7296  {
7297  Error(originFunc, string.Format("Error running rule PSYS_SRC_ACCEL: arg #{0} - parameter 1 must be vector", i + 1));
7298  return;
7299  }
7300  prules.PartAcceleration.X = (float)tempv.x;
7301  prules.PartAcceleration.Y = (float)tempv.y;
7302  prules.PartAcceleration.Z = (float)tempv.z;
7303  break;
7304 
7305  case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
7306  try
7307  {
7308  tmpi = (int)rules.GetLSLIntegerItem(i + 1);
7309  }
7310  catch(InvalidCastException)
7311  {
7312  Error(originFunc, string.Format("Error running rule PSYS_SRC_PATTERN: arg #{0} - parameter 1 must be integer", i + 1));
7313  return;
7314  }
7315  prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
7316  break;
7317 
7318  // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The
7319  // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The
7320  // client tells the difference between the two by looking at the 0x02 bit in
7321  // the PartFlags variable.
7322  case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE:
7323  try
7324  {
7325  tempf = (float)rules.GetLSLFloatItem(i + 1);
7326  }
7327  catch(InvalidCastException)
7328  {
7329  Error(originFunc, string.Format("Error running rule PSYS_SRC_INNERANGLE: arg #{0} - parameter 1 must be float", i + 1));
7330  return;
7331  }
7332  prules.InnerAngle = (float)tempf;
7333  prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
7334  break;
7335 
7336  case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE:
7337  try
7338  {
7339  tempf = (float)rules.GetLSLFloatItem(i + 1);
7340  }
7341  catch(InvalidCastException)
7342  {
7343  Error(originFunc, string.Format("Error running rule PSYS_SRC_OUTERANGLE: arg #{0} - parameter 1 must be float", i + 1));
7344  return;
7345  }
7346  prules.OuterAngle = (float)tempf;
7347  prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
7348  break;
7349 
7350  case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE:
7351  try
7352  {
7353  tmpi = (int)rules.GetLSLIntegerItem(i + 1);
7354  }
7355  catch(InvalidCastException)
7356  {
7357  Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_SOURCE: arg #{0} - parameter 1 must be integer", i + 1));
7358  return;
7359  }
7360  prules.BlendFuncSource = (byte)tmpi;
7361  break;
7362 
7363  case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST:
7364  try
7365  {
7366  tmpi = (int)rules.GetLSLIntegerItem(i + 1);
7367  }
7368  catch(InvalidCastException)
7369  {
7370  Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_DEST: arg #{0} - parameter 1 must be integer", i + 1));
7371  return;
7372  }
7373  prules.BlendFuncDest = (byte)tmpi;
7374  break;
7375 
7376  case (int)ScriptBaseClass.PSYS_PART_START_GLOW:
7377  try
7378  {
7379  tempf = (float)rules.GetLSLFloatItem(i + 1);
7380  }
7381  catch(InvalidCastException)
7382  {
7383  Error(originFunc, string.Format("Error running rule PSYS_PART_START_GLOW: arg #{0} - parameter 1 must be float", i + 1));
7384  return;
7385  }
7386  prules.PartStartGlow = (float)tempf;
7387  break;
7388 
7389  case (int)ScriptBaseClass.PSYS_PART_END_GLOW:
7390  try
7391  {
7392  tempf = (float)rules.GetLSLFloatItem(i + 1);
7393  }
7394  catch(InvalidCastException)
7395  {
7396  Error(originFunc, string.Format("Error running rule PSYS_PART_END_GLOW: arg #{0} - parameter 1 must be float", i + 1));
7397  return;
7398  }
7399  prules.PartEndGlow = (float)tempf;
7400  break;
7401 
7402  case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
7403  try
7404  {
7405  prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1));
7406  }
7407  catch(InvalidCastException)
7408  {
7409  Error(originFunc, string.Format("Error running rule PSYS_SRC_TEXTURE: arg #{0} - parameter 1 must be string or key", i + 1));
7410  return;
7411  }
7412  break;
7413 
7414  case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
7415  try
7416  {
7417  tempf = (float)rules.GetLSLFloatItem(i + 1);
7418  }
7419  catch(InvalidCastException)
7420  {
7421  Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RATE: arg #{0} - parameter 1 must be float", i + 1));
7422  return;
7423  }
7424  prules.BurstRate = (float)tempf;
7425  break;
7426 
7427  case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
7428  try
7429  {
7430  prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
7431  }
7432  catch(InvalidCastException)
7433  {
7434  Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_PART_COUNT: arg #{0} - parameter 1 must be integer", i + 1));
7435  return;
7436  }
7437  break;
7438 
7439  case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
7440  try
7441  {
7442  tempf = (float)rules.GetLSLFloatItem(i + 1);
7443  }
7444  catch(InvalidCastException)
7445  {
7446  Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RADIUS: arg #{0} - parameter 1 must be float", i + 1));
7447  return;
7448  }
7449  prules.BurstRadius = (float)tempf;
7450  break;
7451 
7452  case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
7453  try
7454  {
7455  tempf = (float)rules.GetLSLFloatItem(i + 1);
7456  }
7457  catch(InvalidCastException)
7458  {
7459  Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MIN: arg #{0} - parameter 1 must be float", i + 1));
7460  return;
7461  }
7462  prules.BurstSpeedMin = (float)tempf;
7463  break;
7464 
7465  case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
7466  try
7467  {
7468  tempf = (float)rules.GetLSLFloatItem(i + 1);
7469  }
7470  catch(InvalidCastException)
7471  {
7472  Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MAX: arg #{0} - parameter 1 must be float", i + 1));
7473  return;
7474  }
7475  prules.BurstSpeedMax = (float)tempf;
7476  break;
7477 
7478  case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE:
7479  try
7480  {
7481  tempf = (float)rules.GetLSLFloatItem(i + 1);
7482  }
7483  catch(InvalidCastException)
7484  {
7485  Error(originFunc, string.Format("Error running rule PSYS_SRC_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1));
7486  return;
7487  }
7488  prules.MaxAge = (float)tempf;
7489  break;
7490 
7491  case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY:
7492  UUID key = UUID.Zero;
7493  if (UUID.TryParse(rules.Data[i + 1].ToString(), out key))
7494  {
7495  prules.Target = key;
7496  }
7497  else
7498  {
7499  prules.Target = part.UUID;
7500  }
7501  break;
7502 
7503  case (int)ScriptBaseClass.PSYS_SRC_OMEGA:
7504  // AL: This is an assumption, since it is the only thing that would match.
7505  try
7506  {
7507  tempv = rules.GetVector3Item(i + 1);
7508  }
7509  catch(InvalidCastException)
7510  {
7511  Error(originFunc, string.Format("Error running rule PSYS_SRC_OMEGA: arg #{0} - parameter 1 must be vector", i + 1));
7512  return;
7513  }
7514  prules.AngularVelocity.X = (float)tempv.x;
7515  prules.AngularVelocity.Y = (float)tempv.y;
7516  prules.AngularVelocity.Z = (float)tempv.z;
7517  break;
7518 
7519  case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
7520  try
7521  {
7522  tempf = (float)rules.GetLSLFloatItem(i + 1);
7523  }
7524  catch(InvalidCastException)
7525  {
7526  Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_BEGIN: arg #{0} - parameter 1 must be float", i + 1));
7527  return;
7528  }
7529  prules.InnerAngle = (float)tempf;
7530  prules.PartFlags |= 0x02; // Set new angle format.
7531  break;
7532 
7533  case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END:
7534  try
7535  {
7536  tempf = (float)rules.GetLSLFloatItem(i + 1);
7537  }
7538  catch (InvalidCastException)
7539  {
7540  Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_END: arg #{0} - parameter 1 must be float", i + 1));
7541  return;
7542  }
7543  prules.OuterAngle = (float)tempf;
7544  prules.PartFlags |= 0x02; // Set new angle format.
7545  break;
7546  }
7547 
7548  }
7549  prules.CRC = 1;
7550 
7551  part.AddNewParticleSystem(prules);
7552  part.ParentGroup.HasGroupChanged = true;
7553  }
7554  part.SendFullUpdateToAllClients();
7555  }
7556 
7557  private float validParticleScale(float value)
7558  {
7559  if (value > 4.0f) return 4.0f;
7560  return value;
7561  }
7562 
7563  public void llGroundRepel(double height, int water, double tau)
7564  {
7565  m_host.AddScriptLPS(1);
7566  if (m_host.PhysActor != null)
7567  {
7568  float ground = (float)llGround(new LSL_Types.Vector3(0, 0, 0));
7569  float waterLevel = (float)llWater(new LSL_Types.Vector3(0, 0, 0));
7570  PIDHoverType hoverType = PIDHoverType.Ground;
7571  if (water != 0)
7572  {
7573  hoverType = PIDHoverType.GroundAndWater;
7574  if (ground < waterLevel)
7575  height += waterLevel;
7576  else
7577  height += ground;
7578  }
7579  else
7580  {
7581  height += ground;
7582  }
7583 
7584  m_host.SetHoverHeight((float)height, hoverType, (float)tau);
7585  }
7586  }
7587 
7588  public void llGiveInventoryList(string destination, string category, LSL_List inventory)
7589  {
7590  m_host.AddScriptLPS(1);
7591 
7592  UUID destID;
7593  if (!UUID.TryParse(destination, out destID))
7594  return;
7595 
7596  List<UUID> itemList = new List<UUID>();
7597 
7598  foreach (Object item in inventory.Data)
7599  {
7600  string rawItemString = item.ToString();
7601 
7602  UUID itemID;
7603  if (UUID.TryParse(rawItemString, out itemID))
7604  {
7605  itemList.Add(itemID);
7606  }
7607  else
7608  {
7609  TaskInventoryItem taskItem = m_host.Inventory.GetInventoryItem(rawItemString);
7610 
7611  if (taskItem != null)
7612  itemList.Add(taskItem.ItemID);
7613  }
7614  }
7615 
7616  if (itemList.Count == 0)
7617  return;
7618 
7619  UUID folderID = m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList);
7620 
7621  if (folderID == UUID.Zero)
7622  return;
7623 
7624  if (m_TransferModule != null)
7625  {
7626  byte[] bucket = new byte[] { (byte)AssetType.Folder };
7627 
7628  Vector3 pos = m_host.AbsolutePosition;
7629 
7631  m_host.OwnerID, m_host.Name, destID,
7632  (byte)InstantMessageDialog.TaskInventoryOffered,
7633  false, string.Format("'{0}'", category),
7634 // We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06
7635 // false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z),
7636  folderID, false, pos,
7637  bucket, false);
7638 
7639  m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
7640  }
7641  }
7642 
7643  public void llSetVehicleType(int type)
7644  {
7645  m_host.AddScriptLPS(1);
7646 
7647  if (!m_host.ParentGroup.IsDeleted)
7648  {
7649  m_host.ParentGroup.RootPart.SetVehicleType(type);
7650  }
7651  }
7652 
7653  //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
7654  //CFK 9/28: so these are not complete yet.
7655  public void llSetVehicleFloatParam(int param, LSL_Float value)
7656  {
7657  m_host.AddScriptLPS(1);
7658 
7659  if (!m_host.ParentGroup.IsDeleted)
7660  {
7661  m_host.ParentGroup.RootPart.SetVehicleFloatParam(param, (float)value);
7662  }
7663  }
7664 
7665  //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
7666  //CFK 9/28: so these are not complete yet.
7667  public void llSetVehicleVectorParam(int param, LSL_Vector vec)
7668  {
7669  m_host.AddScriptLPS(1);
7670 
7671  if (!m_host.ParentGroup.IsDeleted)
7672  {
7673  m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec);
7674  }
7675  }
7676 
7677  //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
7678  //CFK 9/28: so these are not complete yet.
7679  public void llSetVehicleRotationParam(int param, LSL_Rotation rot)
7680  {
7681  m_host.AddScriptLPS(1);
7682 
7683  if (!m_host.ParentGroup.IsDeleted)
7684  {
7685  m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot);
7686  }
7687  }
7688 
7689  public void llSetVehicleFlags(int flags)
7690  {
7691  m_host.AddScriptLPS(1);
7692 
7693  if (!m_host.ParentGroup.IsDeleted)
7694  {
7695  m_host.ParentGroup.RootPart.SetVehicleFlags(flags, false);
7696  }
7697  }
7698 
7699  public void llRemoveVehicleFlags(int flags)
7700  {
7701  m_host.AddScriptLPS(1);
7702 
7703  if (!m_host.ParentGroup.IsDeleted)
7704  {
7705  m_host.ParentGroup.RootPart.SetVehicleFlags(flags, true);
7706  }
7707  }
7708 
7709  protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
7710  {
7711  // LSL quaternions can normalize to 0, normal Quaternions can't.
7712  if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
7713  rot.s = 1; // ZERO_ROTATION = 0,0,0,1
7714 
7715  part.SitTargetPosition = offset;
7716  part.SitTargetOrientation = rot;
7717  part.ParentGroup.HasGroupChanged = true;
7718  }
7719 
7720  public void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
7721  {
7722  m_host.AddScriptLPS(1);
7723  SitTarget(m_host, offset, rot);
7724  }
7725 
7726  public void llLinkSitTarget(LSL_Integer link, LSL_Vector offset, LSL_Rotation rot)
7727  {
7728  m_host.AddScriptLPS(1);
7729  if (link == ScriptBaseClass.LINK_ROOT)
7730  SitTarget(m_host.ParentGroup.RootPart, offset, rot);
7731  else if (link == ScriptBaseClass.LINK_THIS)
7732  SitTarget(m_host, offset, rot);
7733  else
7734  {
7735  SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link);
7736  if (null != part)
7737  {
7738  SitTarget(part, offset, rot);
7739  }
7740  }
7741  }
7742 
7744  {
7745  m_host.AddScriptLPS(1);
7746  return m_host.SitTargetAvatar.ToString();
7747  }
7748 
7749  // http://wiki.secondlife.com/wiki/LlAvatarOnLinkSitTarget
7751  {
7752  m_host.AddScriptLPS(1);
7753  if(linknum == ScriptBaseClass.LINK_SET ||
7754  linknum == ScriptBaseClass.LINK_ALL_CHILDREN ||
7755  linknum == ScriptBaseClass.LINK_ALL_OTHERS ||
7756  linknum == 0)
7757  return UUID.Zero.ToString();
7758 
7759  List<SceneObjectPart> parts = GetLinkParts(linknum);
7760  if (parts.Count == 0)
7761  return UUID.Zero.ToString();
7762  return parts[0].SitTargetAvatar.ToString();
7763  }
7764 
7765 
7766  public void llAddToLandPassList(string avatar, double hours)
7767  {
7768  m_host.AddScriptLPS(1);
7769  UUID key;
7770  ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
7771 
7772  if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
7773  {
7774  int expires = 0;
7775  if (hours != 0)
7776  expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours);
7777 
7778  if (UUID.TryParse(avatar, out key))
7779  {
7780  int idx = land.LandData.ParcelAccessList.FindIndex(
7781  delegate(LandAccessEntry e)
7782  {
7783  if (e.AgentID == key && e.Flags == AccessList.Access)
7784  return true;
7785  return false;
7786  });
7787 
7788  if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires)))
7789  return;
7790 
7791  if (idx != -1)
7792  land.LandData.ParcelAccessList.RemoveAt(idx);
7793 
7794  LandAccessEntry entry = new LandAccessEntry();
7795 
7796  entry.AgentID = key;
7797  entry.Flags = AccessList.Access;
7798  entry.Expires = expires;
7799 
7800  land.LandData.ParcelAccessList.Add(entry);
7801 
7802  World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
7803  }
7804  }
7805  ScriptSleep(m_sleepMsOnAddToLandPassList);
7806  }
7807 
7808  public void llSetTouchText(string text)
7809  {
7810  m_host.AddScriptLPS(1);
7811  m_host.TouchName = text;
7812  }
7813 
7814  public void llSetSitText(string text)
7815  {
7816  m_host.AddScriptLPS(1);
7817  m_host.SitName = text;
7818  }
7819 
7820  public void llSetCameraEyeOffset(LSL_Vector offset)
7821  {
7822  m_host.AddScriptLPS(1);
7823  m_host.SetCameraEyeOffset(offset);
7824 
7825  if (m_host.ParentGroup.RootPart.GetCameraEyeOffset() == Vector3.Zero)
7826  m_host.ParentGroup.RootPart.SetCameraEyeOffset(offset);
7827  }
7828 
7829  public void llSetCameraAtOffset(LSL_Vector offset)
7830  {
7831  m_host.AddScriptLPS(1);
7832  m_host.SetCameraAtOffset(offset);
7833 
7834  if (m_host.ParentGroup.RootPart.GetCameraAtOffset() == Vector3.Zero)
7835  m_host.ParentGroup.RootPart.SetCameraAtOffset(offset);
7836  }
7837 
7839  {
7840  m_host.AddScriptLPS(1);
7841 
7842  if (link == ScriptBaseClass.LINK_SET ||
7844  link == ScriptBaseClass.LINK_ALL_OTHERS) return;
7845 
7846  SceneObjectPart part = null;
7847 
7848  switch (link)
7849  {
7850  case ScriptBaseClass.LINK_ROOT:
7851  part = m_host.ParentGroup.RootPart;
7852  break;
7853  case ScriptBaseClass.LINK_THIS:
7854  part = m_host;
7855  break;
7856  default:
7857  part = m_host.ParentGroup.GetLinkNumPart(link);
7858  break;
7859  }
7860 
7861  if (null != part)
7862  {
7863  part.SetCameraEyeOffset(eye);
7864  part.SetCameraAtOffset(at);
7865  }
7866  }
7867 
7868  public LSL_String llDumpList2String(LSL_List src, string seperator)
7869  {
7870  m_host.AddScriptLPS(1);
7871  if (src.Length == 0)
7872  {
7873  return String.Empty;
7874  }
7875  string ret = String.Empty;
7876  foreach (object o in src.Data)
7877  {
7878  ret = ret + o.ToString() + seperator;
7879  }
7880  ret = ret.Substring(0, ret.Length - seperator.Length);
7881  return ret;
7882  }
7883 
7885  {
7886  m_host.AddScriptLPS(1);
7887  bool result = World.ScriptDanger(m_host.LocalId, pos);
7888  if (result)
7889  {
7890  return 1;
7891  }
7892  else
7893  {
7894  return 0;
7895  }
7896 
7897  }
7898 
7899  public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
7900  {
7901  IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
7902 
7903  if (dm == null)
7904  return;
7905 
7906  m_host.AddScriptLPS(1);
7907  UUID av = new UUID();
7908  if (!UUID.TryParse(avatar,out av))
7909  {
7910  Error("llDialog", "First parameter must be a key");
7911  return;
7912  }
7913 
7914  int length = buttons.Length;
7915  if (length < 1)
7916  {
7917  Error("llDialog", "At least 1 button must be shown");
7918  return;
7919  }
7920  if (length > 12)
7921  {
7922  Error("llDialog", "No more than 12 buttons can be shown");
7923  return;
7924  }
7925 
7926  if (message == string.Empty)
7927  {
7928  Error("llDialog", "Empty message");
7929  }
7930  else if (Encoding.UTF8.GetByteCount(message) > 512)
7931  {
7932  Error("llDialog", "Message longer than 512 bytes");
7933  }
7934 
7935  string[] buts = new string[length];
7936  for (int i = 0; i < length; i++)
7937  {
7938  if (buttons.Data[i].ToString() == String.Empty)
7939  {
7940  Error("llDialog", "Button label cannot be blank");
7941  return;
7942  }
7943 /*
7944  if (buttons.Data[i].ToString().Length > 24)
7945  {
7946  Error("llDialog", "Button label cannot be longer than 24 characters");
7947  return;
7948  }
7949 */
7950  buts[i] = buttons.Data[i].ToString();
7951  }
7952 
7953  dm.SendDialogToUser(
7954  av, m_host.Name, m_host.UUID, m_host.OwnerID,
7955  message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
7956 
7957  ScriptSleep(m_sleepMsOnDialog);
7958  }
7959 
7960  public void llVolumeDetect(int detect)
7961  {
7962  m_host.AddScriptLPS(1);
7963 
7964  if (!m_host.ParentGroup.IsDeleted)
7965  m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0);
7966  }
7967 
7968  public void llRemoteLoadScript(string target, string name, int running, int start_param)
7969  {
7970  m_host.AddScriptLPS(1);
7971  Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead");
7972  ScriptSleep(m_sleepMsOnRemoteLoadScript);
7973  }
7974 
7975  public void llSetRemoteScriptAccessPin(int pin)
7976  {
7977  m_host.AddScriptLPS(1);
7978  m_host.ScriptAccessPin = pin;
7979  }
7980 
7981  public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
7982  {
7983  m_host.AddScriptLPS(1);
7984 
7985  UUID destId = UUID.Zero;
7986 
7987  if (!UUID.TryParse(target, out destId))
7988  {
7989  Error("llRemoteLoadScriptPin", "Can't parse key '" + target + "'");
7990  return;
7991  }
7992 
7993  // target must be a different prim than the one containing the script
7994  if (m_host.UUID == destId)
7995  {
7996  return;
7997  }
7998 
7999  // copy the first script found with this inventory name
8000  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
8001 
8002  // make sure the object is a script
8003  if (item == null || item.Type != 10)
8004  {
8005  Error("llRemoteLoadScriptPin", "Can't find script '" + name + "'");
8006  return;
8007  }
8008 
8009  SceneObjectPart dest = World.GetSceneObjectPart(destId);
8010  if (dest != null)
8011  {
8012  if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
8013  {
8014  // the rest of the permission checks are done in RezScript, so check the pin there as well
8015  World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
8016 
8017  if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
8018  m_host.Inventory.RemoveInventoryItem(item.ItemID);
8019  }
8020  }
8021  // this will cause the delay even if the script pin or permissions were wrong - seems ok
8022  ScriptSleep(m_sleepMsOnRemoteLoadScriptPin);
8023  }
8024 
8026  {
8027  m_host.AddScriptLPS(1);
8028  IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
8029  if (xmlrpcMod != null && xmlrpcMod.IsEnabled())
8030  {
8031  UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero);
8032  IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
8033  if (xmlRpcRouter != null)
8034  {
8035  string ExternalHostName = m_ScriptEngine.World.RegionInfo.ExternalHostName;
8036 
8037  xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID,
8038  m_item.ItemID, String.Format("http://{0}:{1}/", ExternalHostName,
8039  xmlrpcMod.Port.ToString()));
8040  }
8041  object[] resobj = new object[]
8042  {
8043  new LSL_Integer(1),
8044  new LSL_String(channelID.ToString()),
8045  new LSL_String(UUID.Zero.ToString()),
8046  new LSL_String(String.Empty),
8047  new LSL_Integer(0),
8048  new LSL_String(String.Empty)
8049  };
8050  m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj,
8051  new DetectParams[0]));
8052  }
8053  ScriptSleep(m_sleepMsOnOpenRemoteDataChannel);
8054  }
8055 
8056  public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
8057  {
8058  m_host.AddScriptLPS(1);
8059  IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
8060  ScriptSleep(m_sleepMsOnSendRemoteData);
8061  if (xmlrpcMod == null)
8062  return "";
8063  return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString();
8064  }
8065 
8066  public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
8067  {
8068  m_host.AddScriptLPS(1);
8069  IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
8070  if (xmlrpcMod != null)
8071  xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
8072  ScriptSleep(m_sleepMsOnRemoteDataReply);
8073  }
8074 
8075  public void llCloseRemoteDataChannel(string channel)
8076  {
8077  m_host.AddScriptLPS(1);
8078 
8079  IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
8080  if (xmlRpcRouter != null)
8081  {
8082  xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID);
8083  }
8084 
8085  IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
8086  if (xmlrpcMod != null)
8087  xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
8088  ScriptSleep(m_sleepMsOnCloseRemoteDataChannel);
8089  }
8090 
8091  public LSL_String llMD5String(string src, int nonce)
8092  {
8093  m_host.AddScriptLPS(1);
8094  return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
8095  }
8096 
8097  public LSL_String llSHA1String(string src)
8098  {
8099  m_host.AddScriptLPS(1);
8100  return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
8101  }
8102 
8103  protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
8104  {
8105  float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
8106  ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
8107  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8108  return shapeBlock;
8109 
8110  if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
8111  holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
8112  holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE &&
8113  holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE)
8114  {
8115  holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT;
8116  }
8117  shapeBlock.PathCurve = pathcurve;
8118  shapeBlock.ProfileCurve = (byte)holeshape; // Set the hole shape.
8119  shapeBlock.ProfileCurve += profileshape; // Add in the profile shape.
8120  if (cut.x < 0f)
8121  {
8122  cut.x = 0f;
8123  }
8124  if (cut.x > 1f)
8125  {
8126  cut.x = 1f;
8127  }
8128  if (cut.y < 0f)
8129  {
8130  cut.y = 0f;
8131  }
8132  if (cut.y > 1f)
8133  {
8134  cut.y = 1f;
8135  }
8136  if (cut.y - cut.x < 0.02f)
8137  {
8138  cut.x = cut.y - 0.02f;
8139  if (cut.x < 0.0f)
8140  {
8141  cut.x = 0.0f;
8142  cut.y = 0.02f;
8143  }
8144  }
8145  shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
8146  shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y));
8147  if (hollow < 0f)
8148  {
8149  hollow = 0f;
8150  }
8151  // If the prim is a Cylinder, Prism, Sphere, Torus or Ring (or not a
8152  // Box or Tube) and the hole shape is a square, hollow is limited to
8153  // a max of 70%. The viewer performs its own check on this value but
8154  // we need to do it here also so llGetPrimitiveParams can have access
8155  // to the correct value.
8156  if (profileshape != (byte)ProfileCurve.Square &&
8157  holeshape == (int)ScriptBaseClass.PRIM_HOLE_SQUARE)
8158  {
8159  if (hollow > 0.70f)
8160  {
8161  hollow = 0.70f;
8162  }
8163  }
8164  // Otherwise, hollow is limited to 99%.
8165  else
8166  {
8167  if (hollow > 0.99f)
8168  {
8169  hollow = 0.99f;
8170  }
8171  }
8172  shapeBlock.ProfileHollow = (ushort)(50000 * hollow);
8173  if (twist.x < -1.0f)
8174  {
8175  twist.x = -1.0f;
8176  }
8177  if (twist.x > 1.0f)
8178  {
8179  twist.x = 1.0f;
8180  }
8181  if (twist.y < -1.0f)
8182  {
8183  twist.y = -1.0f;
8184  }
8185  if (twist.y > 1.0f)
8186  {
8187  twist.y = 1.0f;
8188  }
8189  // A fairly large precision error occurs for some calculations,
8190  // if a float or double is directly cast to a byte or sbyte
8191  // variable, in both .Net and Mono. In .Net, coding
8192  // "(sbyte)(float)(some expression)" corrects the precision
8193  // errors. But this does not work for Mono. This longer coding
8194  // form of creating a tempoary float variable from the
8195  // expression first, then casting that variable to a byte or
8196  // sbyte, works for both .Net and Mono. These types of
8197  // assignments occur in SetPrimtiveBlockShapeParams and
8198  // SetPrimitiveShapeParams in support of llSetPrimitiveParams.
8199  tempFloat = (float)(100.0d * twist.x);
8200  shapeBlock.PathTwistBegin = (sbyte)tempFloat;
8201  tempFloat = (float)(100.0d * twist.y);
8202  shapeBlock.PathTwist = (sbyte)tempFloat;
8203 
8204  shapeBlock.ObjectLocalID = part.LocalId;
8205 
8206  part.Shape.SculptEntry = false;
8207  return shapeBlock;
8208  }
8209 
8210  // Prim type box, cylinder and prism.
8211  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)
8212  {
8213  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8214  return;
8215 
8216  float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
8217  ObjectShapePacket.ObjectDataBlock shapeBlock;
8218 
8219  shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
8220 
8221  if (taper_b.x < 0f)
8222  {
8223  taper_b.x = 0f;
8224  }
8225  if (taper_b.x > 2f)
8226  {
8227  taper_b.x = 2f;
8228  }
8229  if (taper_b.y < 0f)
8230  {
8231  taper_b.y = 0f;
8232  }
8233  if (taper_b.y > 2f)
8234  {
8235  taper_b.y = 2f;
8236  }
8237  tempFloat = (float)(100.0d * (2.0d - taper_b.x));
8238  shapeBlock.PathScaleX = (byte)tempFloat;
8239  tempFloat = (float)(100.0d * (2.0d - taper_b.y));
8240  shapeBlock.PathScaleY = (byte)tempFloat;
8241  if (topshear.x < -0.5f)
8242  {
8243  topshear.x = -0.5f;
8244  }
8245  if (topshear.x > 0.5f)
8246  {
8247  topshear.x = 0.5f;
8248  }
8249  if (topshear.y < -0.5f)
8250  {
8251  topshear.y = -0.5f;
8252  }
8253  if (topshear.y > 0.5f)
8254  {
8255  topshear.y = 0.5f;
8256  }
8257  tempFloat = (float)(100.0d * topshear.x);
8258  shapeBlock.PathShearX = (byte)tempFloat;
8259  tempFloat = (float)(100.0d * topshear.y);
8260  shapeBlock.PathShearY = (byte)tempFloat;
8261 
8262  part.Shape.SculptEntry = false;
8263  part.UpdateShape(shapeBlock);
8264  }
8265 
8266  // Prim type sphere.
8267  protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
8268  {
8269  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8270  return;
8271 
8272  ObjectShapePacket.ObjectDataBlock shapeBlock;
8273 
8274  shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
8275 
8276  // profile/path swapped for a sphere
8277  shapeBlock.PathBegin = shapeBlock.ProfileBegin;
8278  shapeBlock.PathEnd = shapeBlock.ProfileEnd;
8279 
8280  shapeBlock.PathScaleX = 100;
8281  shapeBlock.PathScaleY = 100;
8282 
8283  if (dimple.x < 0f)
8284  {
8285  dimple.x = 0f;
8286  }
8287  if (dimple.x > 1f)
8288  {
8289  dimple.x = 1f;
8290  }
8291  if (dimple.y < 0f)
8292  {
8293  dimple.y = 0f;
8294  }
8295  if (dimple.y > 1f)
8296  {
8297  dimple.y = 1f;
8298  }
8299  if (dimple.y - dimple.x < 0.02f)
8300  {
8301  dimple.x = dimple.y - 0.02f;
8302  if (dimple.x < 0.0f)
8303  {
8304  dimple.x = 0.0f;
8305  dimple.y = 0.02f;
8306  }
8307  }
8308  shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x);
8309  shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y));
8310 
8311  part.Shape.SculptEntry = false;
8312  part.UpdateShape(shapeBlock);
8313  }
8314 
8315  // Prim type torus, tube and ring.
8316  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)
8317  {
8318  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8319  return;
8320 
8321  float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
8322  ObjectShapePacket.ObjectDataBlock shapeBlock;
8323 
8324  shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
8325 
8326  // profile/path swapped for a torrus, tube, ring
8327  shapeBlock.PathBegin = shapeBlock.ProfileBegin;
8328  shapeBlock.PathEnd = shapeBlock.ProfileEnd;
8329 
8330  if (holesize.x < 0.01f)
8331  {
8332  holesize.x = 0.01f;
8333  }
8334  if (holesize.x > 1f)
8335  {
8336  holesize.x = 1f;
8337  }
8338  if (holesize.y < 0.01f)
8339  {
8340  holesize.y = 0.01f;
8341  }
8342  if (holesize.y > 0.5f)
8343  {
8344  holesize.y = 0.5f;
8345  }
8346  tempFloat = (float)(100.0d * (2.0d - holesize.x));
8347  shapeBlock.PathScaleX = (byte)tempFloat;
8348  tempFloat = (float)(100.0d * (2.0d - holesize.y));
8349  shapeBlock.PathScaleY = (byte)tempFloat;
8350  if (topshear.x < -0.5f)
8351  {
8352  topshear.x = -0.5f;
8353  }
8354  if (topshear.x > 0.5f)
8355  {
8356  topshear.x = 0.5f;
8357  }
8358  if (topshear.y < -0.5f)
8359  {
8360  topshear.y = -0.5f;
8361  }
8362  if (topshear.y > 0.5f)
8363  {
8364  topshear.y = 0.5f;
8365  }
8366  tempFloat = (float)(100.0d * topshear.x);
8367  shapeBlock.PathShearX = (byte)tempFloat;
8368  tempFloat = (float)(100.0d * topshear.y);
8369  shapeBlock.PathShearY = (byte)tempFloat;
8370  if (profilecut.x < 0f)
8371  {
8372  profilecut.x = 0f;
8373  }
8374  if (profilecut.x > 1f)
8375  {
8376  profilecut.x = 1f;
8377  }
8378  if (profilecut.y < 0f)
8379  {
8380  profilecut.y = 0f;
8381  }
8382  if (profilecut.y > 1f)
8383  {
8384  profilecut.y = 1f;
8385  }
8386  if (profilecut.y - profilecut.x < 0.02f)
8387  {
8388  profilecut.x = profilecut.y - 0.02f;
8389  if (profilecut.x < 0.0f)
8390  {
8391  profilecut.x = 0.0f;
8392  profilecut.y = 0.02f;
8393  }
8394  }
8395  shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
8396  shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y));
8397  if (taper_a.x < -1f)
8398  {
8399  taper_a.x = -1f;
8400  }
8401  if (taper_a.x > 1f)
8402  {
8403  taper_a.x = 1f;
8404  }
8405  if (taper_a.y < -1f)
8406  {
8407  taper_a.y = -1f;
8408  }
8409  if (taper_a.y > 1f)
8410  {
8411  taper_a.y = 1f;
8412  }
8413  tempFloat = (float)(100.0d * taper_a.x);
8414  shapeBlock.PathTaperX = (sbyte)tempFloat;
8415  tempFloat = (float)(100.0d * taper_a.y);
8416  shapeBlock.PathTaperY = (sbyte)tempFloat;
8417  if (revolutions < 1f)
8418  {
8419  revolutions = 1f;
8420  }
8421  if (revolutions > 4f)
8422  {
8423  revolutions = 4f;
8424  }
8425  tempFloat = 66.66667f * (revolutions - 1.0f);
8426  shapeBlock.PathRevolutions = (byte)tempFloat;
8427  // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
8428  if (radiusoffset < 0f)
8429  {
8430  radiusoffset = 0f;
8431  }
8432  if (radiusoffset > 1f)
8433  {
8434  radiusoffset = 1f;
8435  }
8436  tempFloat = 100.0f * radiusoffset;
8437  shapeBlock.PathRadiusOffset = (sbyte)tempFloat;
8438  if (skew < -0.95f)
8439  {
8440  skew = -0.95f;
8441  }
8442  if (skew > 0.95f)
8443  {
8444  skew = 0.95f;
8445  }
8446  tempFloat = 100.0f * skew;
8447  shapeBlock.PathSkew = (sbyte)tempFloat;
8448 
8449  part.Shape.SculptEntry = false;
8450  part.UpdateShape(shapeBlock);
8451  }
8452 
8453  // Prim type sculpt.
8454  protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
8455  {
8456  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8457  return;
8458 
8459  ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
8460  UUID sculptId;
8461 
8462  if (!UUID.TryParse(map, out sculptId))
8463  sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture);
8464 
8465  if (sculptId == UUID.Zero)
8466  return;
8467 
8468  shapeBlock.PathCurve = pathcurve;
8469  shapeBlock.ObjectLocalID = part.LocalId;
8470  shapeBlock.PathScaleX = 100;
8471  shapeBlock.PathScaleY = 150;
8472 
8473  int flag = type & (ScriptBaseClass.PRIM_SCULPT_FLAG_INVERT | ScriptBaseClass.PRIM_SCULPT_FLAG_MIRROR);
8474 
8475  if (type != (ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER | flag) &&
8476  type != (ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE | flag) &&
8477  type != (ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE | flag) &&
8478  type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
8479  {
8480  // default
8481  type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
8482  }
8483 
8484  part.Shape.SetSculptProperties((byte)type, sculptId);
8485  part.Shape.SculptEntry = true;
8486  part.UpdateShape(shapeBlock);
8487  }
8488 
8489  public void llSetPrimitiveParams(LSL_List rules)
8490  {
8491  m_host.AddScriptLPS(1);
8492 
8493  SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
8494 
8495  ScriptSleep(m_sleepMsOnSetPrimitiveParams);
8496  }
8497 
8498  public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
8499  {
8500  m_host.AddScriptLPS(1);
8501 
8502  SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
8503 
8504  ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams);
8505  }
8506 
8507  public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
8508  {
8509  m_host.AddScriptLPS(1);
8510 
8511  SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
8512  }
8513 
8514  private void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
8515  {
8516  List<object> parts = new List<object>();
8517  List<SceneObjectPart> prims = GetLinkParts(linknumber);
8518  List<ScenePresence> avatars = GetLinkAvatars(linknumber);
8519  foreach (SceneObjectPart p in prims)
8520  parts.Add(p);
8521  foreach (ScenePresence p in avatars)
8522  parts.Add(p);
8523 
8524  LSL_List remaining = new LSL_List();
8525  uint rulesParsed = 0;
8526 
8527  if (parts.Count > 0)
8528  {
8529  foreach (object part in parts)
8530  {
8531  if (part is SceneObjectPart)
8532  remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
8533  else
8534  remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
8535  }
8536 
8537  while (remaining.Length > 2)
8538  {
8539  linknumber = remaining.GetLSLIntegerItem(0);
8540  rules = remaining.GetSublist(1, -1);
8541  parts.Clear();
8542  prims = GetLinkParts(linknumber);
8543  avatars = GetLinkAvatars(linknumber);
8544  foreach (SceneObjectPart p in prims)
8545  parts.Add(p);
8546  foreach (ScenePresence p in avatars)
8547  parts.Add(p);
8548 
8549  remaining = new LSL_List();
8550  foreach (object part in parts)
8551  {
8552  if (part is SceneObjectPart)
8553  remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
8554  else
8555  remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
8556  }
8557  }
8558  }
8559  }
8560 
8561  protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc)
8562  {
8563  LSL_List remaining = new LSL_List();
8564  uint rulesParsed = 0;
8565 
8566  foreach (ISceneEntity entity in entities)
8567  {
8568  if (entity is SceneObjectPart)
8569  remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed);
8570  else
8571  remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed);
8572  }
8573 
8574  while (remaining.Length > 2)
8575  {
8576  int linknumber;
8577  try
8578  {
8579  linknumber = remaining.GetLSLIntegerItem(0);
8580  }
8581  catch(InvalidCastException)
8582  {
8583  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_LINK_TARGET: parameter 2 must be integer", rulesParsed));
8584  return;
8585  }
8586 
8587  rules = remaining.GetSublist(1, -1);
8588  entities = GetLinkEntities(linknumber);
8589 
8590  foreach (ISceneEntity entity in entities)
8591  {
8592  if (entity is SceneObjectPart)
8593  remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed);
8594  else
8595  remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed);
8596  }
8597  }
8598  }
8599 
8601  {
8602  SceneObjectGroup group = m_host.ParentGroup;
8603 
8604  if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
8605  return;
8606  if (group.IsAttachment)
8607  return;
8608 
8609  if (frames.Data.Length > 0) // We are getting a new motion
8610  {
8611  if (group.RootPart.KeyframeMotion != null)
8612  group.RootPart.KeyframeMotion.Delete();
8613  group.RootPart.KeyframeMotion = null;
8614 
8615  int idx = 0;
8616 
8617  KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
8618  KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
8619 
8620  while (idx < options.Data.Length)
8621  {
8622  int option = (int)options.GetLSLIntegerItem(idx++);
8623  int remain = options.Data.Length - idx;
8624 
8625  switch (option)
8626  {
8627  case ScriptBaseClass.KFM_MODE:
8628  if (remain < 1)
8629  break;
8630  int modeval = (int)options.GetLSLIntegerItem(idx++);
8631  switch(modeval)
8632  {
8633  case ScriptBaseClass.KFM_FORWARD:
8634  mode = KeyframeMotion.PlayMode.Forward;
8635  break;
8636  case ScriptBaseClass.KFM_REVERSE:
8637  mode = KeyframeMotion.PlayMode.Reverse;
8638  break;
8639  case ScriptBaseClass.KFM_LOOP:
8640  mode = KeyframeMotion.PlayMode.Loop;
8641  break;
8642  case ScriptBaseClass.KFM_PING_PONG:
8643  mode = KeyframeMotion.PlayMode.PingPong;
8644  break;
8645  }
8646  break;
8647  case ScriptBaseClass.KFM_DATA:
8648  if (remain < 1)
8649  break;
8650  int dataval = (int)options.GetLSLIntegerItem(idx++);
8651  data = (KeyframeMotion.DataFormat)dataval;
8652  break;
8653  }
8654  }
8655 
8656  group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
8657 
8658  idx = 0;
8659 
8660  int elemLength = 2;
8661  if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
8662  elemLength = 3;
8663 
8664  List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
8665  while (idx < frames.Data.Length)
8666  {
8667  int remain = frames.Data.Length - idx;
8668 
8669  if (remain < elemLength)
8670  break;
8671 
8673  frame.Position = null;
8674  frame.Rotation = null;
8675 
8676  if ((data & KeyframeMotion.DataFormat.Translation) != 0)
8677  {
8678  LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
8679  frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
8680  }
8681  if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
8682  {
8683  LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
8684  Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
8685  q.Normalize();
8686  frame.Rotation = q;
8687  }
8688 
8689  float tempf = (float)frames.GetLSLFloatItem(idx++);
8690  frame.TimeMS = (int)(tempf * 1000.0f);
8691 
8692  keyframes.Add(frame);
8693  }
8694 
8695  group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
8696  group.RootPart.KeyframeMotion.Start();
8697  }
8698  else
8699  {
8700  if (group.RootPart.KeyframeMotion == null)
8701  return;
8702 
8703  if (options.Data.Length == 0)
8704  {
8705  group.RootPart.KeyframeMotion.Stop();
8706  return;
8707  }
8708 
8709  int idx = 0;
8710 
8711  while (idx < options.Data.Length)
8712  {
8713  int option = (int)options.GetLSLIntegerItem(idx++);
8714 
8715  switch (option)
8716  {
8717  case ScriptBaseClass.KFM_COMMAND:
8718  int cmd = (int)options.GetLSLIntegerItem(idx++);
8719  switch (cmd)
8720  {
8721  case ScriptBaseClass.KFM_CMD_PLAY:
8722  group.RootPart.KeyframeMotion.Start();
8723  break;
8724  case ScriptBaseClass.KFM_CMD_STOP:
8725  group.RootPart.KeyframeMotion.Stop();
8726  break;
8727  case ScriptBaseClass.KFM_CMD_PAUSE:
8728  group.RootPart.KeyframeMotion.Pause();
8729  break;
8730  }
8731  break;
8732  }
8733  }
8734  }
8735  }
8736 
8738  {
8739  LSL_List result = new LSL_List();
8740 
8741  result.Add(new LSL_Float(m_host.GravityModifier));
8742  result.Add(new LSL_Float(m_host.Restitution));
8743  result.Add(new LSL_Float(m_host.Friction));
8744  result.Add(new LSL_Float(m_host.Density));
8745 
8746  return result;
8747  }
8748 
8749  private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
8750  float material_density, float material_friction,
8751  float material_restitution, float material_gravity_modifier)
8752  {
8753  ExtraPhysicsData physdata = new ExtraPhysicsData();
8754  physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
8755  physdata.Density = part.Density;
8756  physdata.Friction = part.Friction;
8757  physdata.Bounce = part.Restitution;
8758  physdata.GravitationModifier = part.GravityModifier;
8759 
8760  if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
8761  physdata.Density = material_density;
8762  if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
8763  physdata.Friction = material_friction;
8764  if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
8765  physdata.Bounce = material_restitution;
8766  if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
8767  physdata.GravitationModifier = material_gravity_modifier;
8768 
8769  part.UpdateExtraPhysics(physdata);
8770  }
8771 
8772  public void llSetPhysicsMaterial(int material_bits,
8773  float material_gravity_modifier, float material_restitution,
8774  float material_friction, float material_density)
8775  {
8776  SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8777  }
8778 
8779  // vector up using libomv (c&p from sop )
8780  // vector up rotated by r
8781  private Vector3 Zrot(Quaternion r)
8782  {
8783  double x, y, z, m;
8784 
8785  m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
8786  if (Math.Abs(1.0 - m) > 0.000001)
8787  {
8788  m = 1.0 / Math.Sqrt(m);
8789  r.X *= (float)m;
8790  r.Y *= (float)m;
8791  r.Z *= (float)m;
8792  r.W *= (float)m;
8793  }
8794 
8795  x = 2 * (r.X * r.Z + r.Y * r.W);
8796  y = 2 * (-r.X * r.W + r.Y * r.Z);
8797  z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
8798 
8799  return new Vector3((float)x, (float)y, (float)z);
8800  }
8801 
8802  protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
8803  {
8804  if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8805  return new LSL_List();
8806 
8807  int idx = 0;
8808  int idxStart = 0;
8809 
8810  SceneObjectGroup parentgrp = part.ParentGroup;
8811 
8812  bool positionChanged = false;
8813  LSL_Vector currentPosition = GetPartLocalPos(part);
8814 
8815  try
8816  {
8817  while (idx < rules.Length)
8818  {
8819  ++rulesParsed;
8820  int code = rules.GetLSLIntegerItem(idx++);
8821 
8822  int remain = rules.Length - idx;
8823  idxStart = idx;
8824 
8825  int face;
8826  LSL_Vector v;
8827 
8828  switch (code)
8829  {
8830  case ScriptBaseClass.PRIM_POSITION:
8831  case ScriptBaseClass.PRIM_POS_LOCAL:
8832  if (remain < 1)
8833  return new LSL_List();
8834 
8835  try
8836  {
8837  v = rules.GetVector3Item(idx++);
8838  }
8839  catch(InvalidCastException)
8840  {
8841  if(code == ScriptBaseClass.PRIM_POSITION)
8842  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1));
8843  else
8844  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1));
8845  return new LSL_List();
8846  }
8847  if (part.IsRoot && !part.ParentGroup.IsAttachment)
8848  currentPosition = GetSetPosTarget(part, v, currentPosition, true);
8849  else
8850  currentPosition = GetSetPosTarget(part, v, currentPosition, false);
8851  positionChanged = true;
8852 
8853  break;
8854  case ScriptBaseClass.PRIM_SIZE:
8855  if (remain < 1)
8856  return new LSL_List();
8857 
8858  v=rules.GetVector3Item(idx++);
8859  SetScale(part, v);
8860 
8861  break;
8862  case ScriptBaseClass.PRIM_ROTATION:
8863  if (remain < 1)
8864  return new LSL_List();
8865  LSL_Rotation q;
8866  try
8867  {
8868  q = rules.GetQuaternionItem(idx++);
8869  }
8870  catch(InvalidCastException)
8871  {
8872  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 1 must be rotation", rulesParsed, idx - idxStart - 1));
8873  return new LSL_List();
8874  }
8875  // try to let this work as in SL...
8876  if (part.ParentID == 0 || (part.ParentGroup != null && part == part.ParentGroup.RootPart))
8877  {
8878  // special case: If we are root, rotate complete SOG to new rotation
8879  SetRot(part, q);
8880  }
8881  else
8882  {
8883  // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
8884  SceneObjectPart rootPart = part.ParentGroup.RootPart;
8885  SetRot(part, rootPart.RotationOffset * (Quaternion)q);
8886  }
8887 
8888  break;
8889 
8890  case ScriptBaseClass.PRIM_TYPE:
8891  if (remain < 3)
8892  return new LSL_List();
8893 
8894  try
8895  {
8896  code = (int)rules.GetLSLIntegerItem(idx++);
8897  }
8898  catch(InvalidCastException)
8899  {
8900  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE: arg #{1} - parameter 1 must be integer", rulesParsed, idx - idxStart - 1));
8901  return new LSL_List();
8902  }
8903 
8904  remain = rules.Length - idx;
8905  float hollow;
8906  LSL_Vector twist;
8907  LSL_Vector taper_b;
8908  LSL_Vector topshear;
8909  float revolutions;
8910  float radiusoffset;
8911  float skew;
8912  LSL_Vector holesize;
8913  LSL_Vector profilecut;
8914 
8915  switch (code)
8916  {
8917  case ScriptBaseClass.PRIM_TYPE_BOX:
8918  if (remain < 6)
8919  return new LSL_List();
8920 
8921  try
8922  {
8923  face = (int)rules.GetLSLIntegerItem(idx++);
8924  }
8925  catch(InvalidCastException)
8926  {
8927  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
8928  return new LSL_List();
8929  }
8930  try
8931  {
8932  v = rules.GetVector3Item(idx++); // cut
8933  }
8934  catch(InvalidCastException)
8935  {
8936  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
8937  return new LSL_List();
8938  }
8939  try
8940  {
8941  hollow = (float)rules.GetLSLFloatItem(idx++);
8942  }
8943  catch(InvalidCastException)
8944  {
8945  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
8946  return new LSL_List();
8947  }
8948  try
8949  {
8950  twist = rules.GetVector3Item(idx++);
8951  }
8952  catch(InvalidCastException)
8953  {
8954  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 5 must be vector", rulesParsed, idx - idxStart - 1));
8955  return new LSL_List();
8956  }
8957  try
8958  {
8959  taper_b = rules.GetVector3Item(idx++);
8960  }
8961  catch(InvalidCastException)
8962  {
8963  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8964  return new LSL_List();
8965  }
8966  try
8967  {
8968  topshear = rules.GetVector3Item(idx++);
8969  }
8970  catch(InvalidCastException)
8971  {
8972  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8973  return new LSL_List();
8974  }
8975 
8976  SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
8977  (byte)ProfileShape.Square, (byte)Extrusion.Straight);
8978  break;
8979 
8980  case ScriptBaseClass.PRIM_TYPE_CYLINDER:
8981  if (remain < 6)
8982  return new LSL_List();
8983 
8984  try
8985  {
8986  face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8987  }
8988  catch(InvalidCastException)
8989  {
8990  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8991  return new LSL_List();
8992  }
8993  try
8994  {
8995  v = rules.GetVector3Item(idx++); // cut
8996  }
8997  catch(InvalidCastException)
8998  {
8999  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
9000  return new LSL_List();
9001  }
9002  try
9003  {
9004  hollow = (float)rules.GetLSLFloatItem(idx++);
9005  }
9006  catch(InvalidCastException)
9007  {
9008  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9009  return new LSL_List();
9010  }
9011  try
9012  {
9013  twist = rules.GetVector3Item(idx++);
9014  }
9015  catch(InvalidCastException)
9016  {
9017  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
9018  return new LSL_List();
9019  }
9020  try
9021  {
9022  taper_b = rules.GetVector3Item(idx++);
9023  }
9024  catch(InvalidCastException)
9025  {
9026  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
9027  return new LSL_List();
9028  }
9029  try
9030  {
9031  topshear = rules.GetVector3Item(idx++);
9032  }
9033  catch(InvalidCastException)
9034  {
9035  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
9036  return new LSL_List();
9037  }
9038  SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
9039  (byte)ProfileShape.Circle, (byte)Extrusion.Straight);
9040  break;
9041 
9042  case ScriptBaseClass.PRIM_TYPE_PRISM:
9043  if (remain < 6)
9044  return new LSL_List();
9045 
9046  try
9047  {
9048  face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
9049  }
9050  catch(InvalidCastException)
9051  {
9052  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9053  return new LSL_List();
9054  }
9055  try
9056  {
9057  v = rules.GetVector3Item(idx++); //cut
9058  }
9059  catch(InvalidCastException)
9060  {
9061  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
9062  return new LSL_List();
9063  }
9064  try
9065  {
9066  hollow = (float)rules.GetLSLFloatItem(idx++);
9067  }
9068  catch(InvalidCastException)
9069  {
9070  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9071  return new LSL_List();
9072  }
9073  try
9074  {
9075  twist = rules.GetVector3Item(idx++);
9076  }
9077  catch(InvalidCastException)
9078  {
9079  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
9080  return new LSL_List();
9081  }
9082  try
9083  {
9084  taper_b = rules.GetVector3Item(idx++);
9085  }
9086  catch(InvalidCastException)
9087  {
9088  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
9089  return new LSL_List();
9090  }
9091  try
9092  {
9093  topshear = rules.GetVector3Item(idx++);
9094  }
9095  catch(InvalidCastException)
9096  {
9097  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
9098  return new LSL_List();
9099  }
9100  SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
9101  (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight);
9102  break;
9103 
9104  case ScriptBaseClass.PRIM_TYPE_SPHERE:
9105  if (remain < 5)
9106  return new LSL_List();
9107 
9108  try
9109  {
9110  face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
9111  }
9112  catch(InvalidCastException)
9113  {
9114  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9115  return new LSL_List();
9116  }
9117  try
9118  {
9119  v = rules.GetVector3Item(idx++); // cut
9120  }
9121  catch(InvalidCastException)
9122  {
9123  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
9124  return new LSL_List();
9125  }
9126  try
9127  {
9128  hollow = (float)rules.GetLSLFloatItem(idx++);
9129  }
9130  catch(InvalidCastException)
9131  {
9132  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9133  return new LSL_List();
9134  }
9135  try
9136  {
9137  twist = rules.GetVector3Item(idx++);
9138  }
9139  catch(InvalidCastException)
9140  {
9141  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
9142  return new LSL_List();
9143  }
9144  try
9145  {
9146  taper_b = rules.GetVector3Item(idx++); // dimple
9147  }
9148  catch(InvalidCastException)
9149  {
9150  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
9151  return new LSL_List();
9152  }
9153  SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b,
9154  (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1);
9155  break;
9156 
9157  case ScriptBaseClass.PRIM_TYPE_TORUS:
9158  if (remain < 11)
9159  return new LSL_List();
9160 
9161  try
9162  {
9163  face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
9164  }
9165  catch(InvalidCastException)
9166  {
9167  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9168  return new LSL_List();
9169  }
9170  try
9171  {
9172  v = rules.GetVector3Item(idx++); //cut
9173  }
9174  catch(InvalidCastException)
9175  {
9176  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
9177  return new LSL_List();
9178  }
9179  try
9180  {
9181  hollow = (float)rules.GetLSLFloatItem(idx++);
9182  }
9183  catch(InvalidCastException)
9184  {
9185  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9186  return new LSL_List();
9187  }
9188  try
9189  {
9190  twist = rules.GetVector3Item(idx++);
9191  }
9192  catch(InvalidCastException)
9193  {
9194  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
9195  return new LSL_List();
9196  }
9197  try
9198  {
9199  holesize = rules.GetVector3Item(idx++);
9200  }
9201  catch(InvalidCastException)
9202  {
9203  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
9204  return new LSL_List();
9205  }
9206  try
9207  {
9208  topshear = rules.GetVector3Item(idx++);
9209  }
9210  catch(InvalidCastException)
9211  {
9212  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
9213  return new LSL_List();
9214  }
9215  try
9216  {
9217  profilecut = rules.GetVector3Item(idx++);
9218  }
9219  catch(InvalidCastException)
9220  {
9221  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
9222  return new LSL_List();
9223  }
9224  try
9225  {
9226  taper_b = rules.GetVector3Item(idx++); // taper_a
9227  }
9228  catch(InvalidCastException)
9229  {
9230  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
9231  return new LSL_List();
9232  }
9233  try
9234  {
9235  revolutions = (float)rules.GetLSLFloatItem(idx++);
9236  }
9237  catch(InvalidCastException)
9238  {
9239  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
9240  return new LSL_List();
9241  }
9242  try
9243  {
9244  radiusoffset = (float)rules.GetLSLFloatItem(idx++);
9245  }
9246  catch(InvalidCastException)
9247  {
9248  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
9249  return new LSL_List();
9250  }
9251  try
9252  {
9253  skew = (float)rules.GetLSLFloatItem(idx++);
9254  }
9255  catch(InvalidCastException)
9256  {
9257  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 13 must be vector", rulesParsed, idx - idxStart - 1));
9258  return new LSL_List();
9259  }
9260  SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
9261  revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1);
9262  break;
9263 
9264  case ScriptBaseClass.PRIM_TYPE_TUBE:
9265  if (remain < 11)
9266  return new LSL_List();
9267 
9268  try
9269  {
9270  face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
9271  }
9272  catch(InvalidCastException)
9273  {
9274  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9275  return new LSL_List();
9276  }
9277  try
9278  {
9279  v = rules.GetVector3Item(idx++); //cut
9280  }
9281  catch(InvalidCastException)
9282  {
9283  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
9284  return new LSL_List();
9285  }
9286  try
9287  {
9288  hollow = (float)rules.GetLSLFloatItem(idx++);
9289  }
9290  catch(InvalidCastException)
9291  {
9292  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9293  return new LSL_List();
9294  }
9295  try
9296  {
9297  twist = rules.GetVector3Item(idx++);
9298  }
9299  catch(InvalidCastException)
9300  {
9301  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
9302  return new LSL_List();
9303  }
9304  try
9305  {
9306  holesize = rules.GetVector3Item(idx++);
9307  }
9308  catch(InvalidCastException)
9309  {
9310  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
9311  return new LSL_List();
9312  }
9313  try
9314  {
9315  topshear = rules.GetVector3Item(idx++);
9316  }
9317  catch(InvalidCastException)
9318  {
9319  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
9320  return new LSL_List();
9321  }
9322  try
9323  {
9324  profilecut = rules.GetVector3Item(idx++);
9325  }
9326  catch(InvalidCastException)
9327  {
9328  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
9329  return new LSL_List();
9330  }
9331  try
9332  {
9333  taper_b = rules.GetVector3Item(idx++); // taper_a
9334  }
9335  catch(InvalidCastException)
9336  {
9337  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
9338  return new LSL_List();
9339  }
9340  try
9341  {
9342  revolutions = (float)rules.GetLSLFloatItem(idx++);
9343  }
9344  catch(InvalidCastException)
9345  {
9346  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
9347  return new LSL_List();
9348  }
9349  try
9350  {
9351  radiusoffset = (float)rules.GetLSLFloatItem(idx++);
9352  }
9353  catch(InvalidCastException)
9354  {
9355  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
9356  return new LSL_List();
9357  }
9358  try
9359  {
9360  skew = (float)rules.GetLSLFloatItem(idx++);
9361  }
9362  catch(InvalidCastException)
9363  {
9364  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1));
9365  return new LSL_List();
9366  }
9367  SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
9368  revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1);
9369  break;
9370 
9371  case ScriptBaseClass.PRIM_TYPE_RING:
9372  if (remain < 11)
9373  return new LSL_List();
9374 
9375  try
9376  {
9377  face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
9378  }
9379  catch(InvalidCastException)
9380  {
9381  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9382  return new LSL_List();
9383  }
9384  try
9385  {
9386  v = rules.GetVector3Item(idx++); //cut
9387  }
9388  catch(InvalidCastException)
9389  {
9390  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
9391  return new LSL_List();
9392  }
9393  try
9394  {
9395  hollow = (float)rules.GetLSLFloatItem(idx++);
9396  }
9397  catch(InvalidCastException)
9398  {
9399  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9400  return new LSL_List();
9401  }
9402  try
9403  {
9404  twist = rules.GetVector3Item(idx++);
9405  }
9406  catch(InvalidCastException)
9407  {
9408  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
9409  return new LSL_List();
9410  }
9411  try
9412  {
9413  holesize = rules.GetVector3Item(idx++);
9414  }
9415  catch(InvalidCastException)
9416  {
9417  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
9418  return new LSL_List();
9419  }
9420  try
9421  {
9422  topshear = rules.GetVector3Item(idx++);
9423  }
9424  catch(InvalidCastException)
9425  {
9426  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
9427  return new LSL_List();
9428  }
9429  try
9430  {
9431  profilecut = rules.GetVector3Item(idx++);
9432  }
9433  catch(InvalidCastException)
9434  {
9435  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
9436  return new LSL_List();
9437  }
9438  try
9439  {
9440  taper_b = rules.GetVector3Item(idx++); // taper_a
9441  }
9442  catch(InvalidCastException)
9443  {
9444  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
9445  return new LSL_List();
9446  }
9447  try
9448  {
9449  revolutions = (float)rules.GetLSLFloatItem(idx++);
9450  }
9451  catch(InvalidCastException)
9452  {
9453  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
9454  return new LSL_List();
9455  }
9456  try
9457  {
9458  radiusoffset = (float)rules.GetLSLFloatItem(idx++);
9459  }
9460  catch(InvalidCastException)
9461  {
9462  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
9463  return new LSL_List();
9464  }
9465  try
9466  {
9467  skew = (float)rules.GetLSLFloatItem(idx++);
9468  }
9469  catch(InvalidCastException)
9470  {
9471  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1));
9472  return new LSL_List();
9473  }
9474  SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
9475  revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1);
9476  break;
9477 
9478  case ScriptBaseClass.PRIM_TYPE_SCULPT:
9479  if (remain < 2)
9480  return new LSL_List();
9481 
9482  string map = rules.Data[idx++].ToString();
9483  try
9484  {
9485  face = (int)rules.GetLSLIntegerItem(idx++); // type
9486  }
9487  catch(InvalidCastException)
9488  {
9489  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SCULPT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
9490  return new LSL_List();
9491  }
9492  SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1);
9493  break;
9494  }
9495 
9496  break;
9497 
9498  case ScriptBaseClass.PRIM_TEXTURE:
9499  if (remain < 5)
9500  return new LSL_List();
9501 
9502  face=(int)rules.GetLSLIntegerItem(idx++);
9503  string tex;
9504  LSL_Vector repeats;
9505  LSL_Vector offsets;
9506  double rotation;
9507 
9508  tex = rules.Data[idx++].ToString();
9509  try
9510  {
9511  repeats = rules.GetVector3Item(idx++);
9512  }
9513  catch(InvalidCastException)
9514  {
9515  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
9516  return new LSL_List();
9517  }
9518  try
9519  {
9520  offsets = rules.GetVector3Item(idx++);
9521  }
9522  catch(InvalidCastException)
9523  {
9524  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
9525  return new LSL_List();
9526  }
9527  try
9528  {
9529  rotation = (double)rules.GetLSLFloatItem(idx++);
9530  }
9531  catch(InvalidCastException)
9532  {
9533  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9534  return new LSL_List();
9535  }
9536 
9537  SetTexture(part, tex, face);
9538  ScaleTexture(part, repeats.x, repeats.y, face);
9539  OffsetTexture(part, offsets.x, offsets.y, face);
9540  RotateTexture(part, rotation, face);
9541 
9542  break;
9543 
9544  case ScriptBaseClass.PRIM_COLOR:
9545  if (remain < 3)
9546  return new LSL_List();
9547 
9548  LSL_Vector color;
9549  double alpha;
9550 
9551  try
9552  {
9553  face = (int)rules.GetLSLIntegerItem(idx++);
9554  }
9555  catch(InvalidCastException)
9556  {
9557  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9558  return new LSL_List();
9559  }
9560  try
9561  {
9562  color = rules.GetVector3Item(idx++);
9563  }
9564  catch(InvalidCastException)
9565  {
9566  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
9567  return new LSL_List();
9568  }
9569  try
9570  {
9571  alpha = (double)rules.GetLSLFloatItem(idx++);
9572  }
9573  catch(InvalidCastException)
9574  {
9575  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9576  return new LSL_List();
9577  }
9578 
9579  part.SetFaceColorAlpha(face, color, alpha);
9580 
9581  break;
9582 
9583  case ScriptBaseClass.PRIM_FLEXIBLE:
9584  if (remain < 7)
9585  return new LSL_List();
9586  bool flexi;
9587  int softness;
9588  float gravity;
9589  float friction;
9590  float wind;
9591  float tension;
9592  LSL_Vector force;
9593 
9594  try
9595  {
9596  flexi = rules.GetLSLIntegerItem(idx++);
9597  }
9598  catch(InvalidCastException)
9599  {
9600  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9601  return new LSL_List();
9602  }
9603  try
9604  {
9605  softness = rules.GetLSLIntegerItem(idx++);
9606  }
9607  catch(InvalidCastException)
9608  {
9609  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9610  return new LSL_List();
9611  }
9612  try
9613  {
9614  gravity = (float)rules.GetLSLFloatItem(idx++);
9615  }
9616  catch(InvalidCastException)
9617  {
9618  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9619  return new LSL_List();
9620  }
9621  try
9622  {
9623  friction = (float)rules.GetLSLFloatItem(idx++);
9624  }
9625  catch(InvalidCastException)
9626  {
9627  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9628  return new LSL_List();
9629  }
9630  try
9631  {
9632  wind = (float)rules.GetLSLFloatItem(idx++);
9633  }
9634  catch(InvalidCastException)
9635  {
9636  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1));
9637  return new LSL_List();
9638  }
9639  try
9640  {
9641  tension = (float)rules.GetLSLFloatItem(idx++);
9642  }
9643  catch(InvalidCastException)
9644  {
9645  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 7 must be float", rulesParsed, idx - idxStart - 1));
9646  return new LSL_List();
9647  }
9648  try
9649  {
9650  force = rules.GetVector3Item(idx++);
9651  }
9652  catch(InvalidCastException)
9653  {
9654  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
9655  return new LSL_List();
9656  }
9657 
9658  SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force);
9659 
9660  break;
9661 
9662  case ScriptBaseClass.PRIM_POINT_LIGHT:
9663  if (remain < 5)
9664  return new LSL_List();
9665  bool light;
9666  LSL_Vector lightcolor;
9667  float intensity;
9668  float radius;
9669  float falloff;
9670 
9671  try
9672  {
9673  light = rules.GetLSLIntegerItem(idx++);
9674  }
9675  catch(InvalidCastException)
9676  {
9677  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9678  return new LSL_List();
9679  }
9680  try
9681  {
9682  lightcolor = rules.GetVector3Item(idx++);
9683  }
9684  catch(InvalidCastException)
9685  {
9686  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
9687  return new LSL_List();
9688  }
9689  try
9690  {
9691  intensity = (float)rules.GetLSLFloatItem(idx++);
9692  }
9693  catch(InvalidCastException)
9694  {
9695  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9696  return new LSL_List();
9697  }
9698  try
9699  {
9700  radius = (float)rules.GetLSLFloatItem(idx++);
9701  }
9702  catch(InvalidCastException)
9703  {
9704  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9705  return new LSL_List();
9706  }
9707  try
9708  {
9709  falloff = (float)rules.GetLSLFloatItem(idx++);
9710  }
9711  catch(InvalidCastException)
9712  {
9713  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1));
9714  return new LSL_List();
9715  }
9716 
9717  SetPointLight(part, light, lightcolor, intensity, radius, falloff);
9718 
9719  break;
9720 
9721  case ScriptBaseClass.PRIM_GLOW:
9722  if (remain < 2)
9723  return new LSL_List();
9724 
9725  float glow;
9726 
9727  try
9728  {
9729  face = rules.GetLSLIntegerItem(idx++);
9730  }
9731  catch(InvalidCastException)
9732  {
9733  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9734  return new LSL_List();
9735  }
9736  try
9737  {
9738  glow = (float)rules.GetLSLFloatItem(idx++);
9739  }
9740  catch(InvalidCastException)
9741  {
9742  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1));
9743  return new LSL_List();
9744  }
9745 
9746  SetGlow(part, face, glow);
9747 
9748  break;
9749 
9750  case ScriptBaseClass.PRIM_BUMP_SHINY:
9751  if (remain < 3)
9752  return new LSL_List();
9753 
9754  int shiny;
9755  Bumpiness bump;
9756 
9757  try
9758  {
9759  face = (int)rules.GetLSLIntegerItem(idx++);
9760  }
9761  catch(InvalidCastException)
9762  {
9763  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9764  return new LSL_List();
9765  }
9766  try
9767  {
9768  shiny = (int)rules.GetLSLIntegerItem(idx++);
9769  }
9770  catch(InvalidCastException)
9771  {
9772  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9773  return new LSL_List();
9774  }
9775  try
9776  {
9777  bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++);
9778  }
9779  catch(InvalidCastException)
9780  {
9781  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
9782  return new LSL_List();
9783  }
9784 
9785  SetShiny(part, face, shiny, bump);
9786 
9787  break;
9788 
9789  case ScriptBaseClass.PRIM_FULLBRIGHT:
9790  if (remain < 2)
9791  return new LSL_List();
9792  bool st;
9793 
9794  try
9795  {
9796  face = rules.GetLSLIntegerItem(idx++);
9797  }
9798  catch(InvalidCastException)
9799  {
9800  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9801  return new LSL_List();
9802  }
9803  try
9804  {
9805  st = rules.GetLSLIntegerItem(idx++);
9806  }
9807  catch(InvalidCastException)
9808  {
9809  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
9810  return new LSL_List();
9811  }
9812  SetFullBright(part, face , st);
9813  break;
9814 
9815  case ScriptBaseClass.PRIM_MATERIAL:
9816  if (remain < 1)
9817  return new LSL_List();
9818  int mat;
9819 
9820  try
9821  {
9822  mat = rules.GetLSLIntegerItem(idx++);
9823  }
9824  catch(InvalidCastException)
9825  {
9826  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_MATERIAL: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9827  return new LSL_List();
9828  }
9829  if (mat < 0 || mat > 7)
9830  return new LSL_List();
9831 
9832  part.Material = Convert.ToByte(mat);
9833  break;
9834 
9835  case ScriptBaseClass.PRIM_PHANTOM:
9836  if (remain < 1)
9837  return new LSL_List();
9838 
9839  string ph = rules.Data[idx++].ToString();
9840  part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1"));
9841 
9842  break;
9843 
9844  case ScriptBaseClass.PRIM_PHYSICS:
9845  if (remain < 1)
9846  return new LSL_List();
9847  string phy = rules.Data[idx++].ToString();
9848  part.ScriptSetPhysicsStatus(phy.Equals("1"));
9849  break;
9850 
9851  case ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
9852  if (remain < 1)
9853  return new LSL_List();
9854 
9855  int shape_type;
9856 
9857  try
9858  {
9859  shape_type = rules.GetLSLIntegerItem(idx++);
9860  }
9861  catch(InvalidCastException)
9862  {
9863  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_PHYSICS_SHAPE_TYPE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9864  return new LSL_List();
9865  }
9866 
9867  ExtraPhysicsData physdata = new ExtraPhysicsData();
9868  physdata.Density = part.Density;
9869  physdata.Bounce = part.Restitution;
9870  physdata.GravitationModifier = part.GravityModifier;
9871  physdata.PhysShapeType = (PhysShapeType)shape_type;
9872 
9873  part.UpdateExtraPhysics(physdata);
9874 
9875  break;
9876 
9877  case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
9878  if (remain < 5)
9879  return new LSL_List();
9880 
9881  int material_bits = rules.GetLSLIntegerItem(idx++);
9882  float material_density = (float)rules.GetLSLFloatItem(idx++);
9883  float material_friction = (float)rules.GetLSLFloatItem(idx++);
9884  float material_restitution = (float)rules.GetLSLFloatItem(idx++);
9885  float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
9886 
9887  SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
9888 
9889  break;
9890 
9891  case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
9892  if (remain < 1)
9893  return new LSL_List();
9894  string temp = rules.Data[idx++].ToString();
9895 
9896  part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1"));
9897 
9898  break;
9899 
9900  case ScriptBaseClass.PRIM_TEXGEN:
9901  if (remain < 2)
9902  return new LSL_List();
9903  //face,type
9904  int style;
9905 
9906  try
9907  {
9908  face = rules.GetLSLIntegerItem(idx++);
9909  }
9910  catch(InvalidCastException)
9911  {
9912  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9913  return new LSL_List();
9914  }
9915  try
9916  {
9917  style = rules.GetLSLIntegerItem(idx++);
9918  }
9919  catch(InvalidCastException)
9920  {
9921  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9922  return new LSL_List();
9923  }
9924  SetTexGen(part, face, style);
9925  break;
9926  case ScriptBaseClass.PRIM_TEXT:
9927  if (remain < 3)
9928  return new LSL_List();
9929  string primText;
9930  LSL_Vector primTextColor;
9931  LSL_Float primTextAlpha;
9932 
9933  try
9934  {
9935  primText = rules.GetLSLStringItem(idx++);
9936  }
9937  catch(InvalidCastException)
9938  {
9939  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9940  return new LSL_List();
9941  }
9942  try
9943  {
9944  primTextColor = rules.GetVector3Item(idx++);
9945  }
9946  catch(InvalidCastException)
9947  {
9948  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
9949  return new LSL_List();
9950  }
9951  try
9952  {
9953  primTextAlpha = rules.GetLSLFloatItem(idx++);
9954  }
9955  catch(InvalidCastException)
9956  {
9957  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9958  return new LSL_List();
9959  }
9960  Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f);
9961  part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
9962 
9963  break;
9964 
9965  case ScriptBaseClass.PRIM_NAME:
9966  if (remain < 1)
9967  return new LSL_List();
9968  try
9969  {
9970  string primName = rules.GetLSLStringItem(idx++);
9971  part.Name = primName;
9972  }
9973  catch(InvalidCastException)
9974  {
9975  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NAME: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9976  return new LSL_List();
9977  }
9978  break;
9979  case ScriptBaseClass.PRIM_DESC:
9980  if (remain < 1)
9981  return new LSL_List();
9982  try
9983  {
9984  string primDesc = rules.GetLSLStringItem(idx++);
9985  part.Description = primDesc;
9986  }
9987  catch(InvalidCastException)
9988  {
9989  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_DESC: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9990  return new LSL_List();
9991  }
9992  break;
9993  case ScriptBaseClass.PRIM_ROT_LOCAL:
9994  if (remain < 1)
9995  return new LSL_List();
9996  LSL_Rotation rot;
9997  try
9998  {
9999  rot = rules.GetQuaternionItem(idx++);
10000  }
10001  catch(InvalidCastException)
10002  {
10003  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
10004  return new LSL_List();
10005  }
10006  SetRot(part, rot);
10007  break;
10008 
10009  case ScriptBaseClass.PRIM_OMEGA:
10010  if (remain < 3)
10011  return new LSL_List();
10012  LSL_Vector axis;
10013  LSL_Float spinrate;
10014  LSL_Float gain;
10015 
10016  try
10017  {
10018  axis = rules.GetVector3Item(idx++);
10019  }
10020  catch(InvalidCastException)
10021  {
10022  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
10023  return new LSL_List();
10024  }
10025  try
10026  {
10027  spinrate = rules.GetLSLFloatItem(idx++);
10028  }
10029  catch(InvalidCastException)
10030  {
10031  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1));
10032  return new LSL_List();
10033  }
10034  try
10035  {
10036  gain = rules.GetLSLFloatItem(idx++);
10037  }
10038  catch(InvalidCastException)
10039  {
10040  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
10041  return new LSL_List();
10042  }
10043  TargetOmega(part, axis, (double)spinrate, (double)gain);
10044  break;
10045 
10046  case ScriptBaseClass.PRIM_SLICE:
10047  if (remain < 1)
10048  return new LSL_List();
10049  LSL_Vector slice;
10050  try
10051  {
10052  slice = rules.GetVector3Item(idx++);
10053  }
10054  catch(InvalidCastException)
10055  {
10056  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SLICE: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
10057  return new LSL_List();
10058  }
10059  part.UpdateSlice((float)slice.x, (float)slice.y);
10060  break;
10061 
10062  case ScriptBaseClass.PRIM_LINK_TARGET:
10063  if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
10064  return new LSL_List();
10065 
10066  return rules.GetSublist(idx, -1);
10067 
10068  default:
10069  Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - unsupported parameter", rulesParsed, idx - idxStart));
10070  return new LSL_List();
10071  }
10072  }
10073  }
10074  catch (InvalidCastException e)
10075  {
10076  Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message);
10077  }
10078  finally
10079  {
10080  if (positionChanged)
10081  {
10082  if (part.ParentGroup.RootPart == part)
10083  {
10084  SceneObjectGroup parent = part.ParentGroup;
10085 // Util.FireAndForget(delegate(object x) {
10086  parent.UpdateGroupPosition(currentPosition);
10087 // });
10088  }
10089  else
10090  {
10091  part.OffsetPosition = currentPosition;
10092 // SceneObjectGroup parent = part.ParentGroup;
10093 // parent.HasGroupChanged = true;
10094 // parent.ScheduleGroupForTerseUpdate();
10095  part.ScheduleTerseUpdate();
10096  }
10097  }
10098  }
10099 
10100  return new LSL_List();
10101  }
10102 
10103  protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed)
10104  {
10105  int idx = 0;
10106  int idxStart = 0;
10107 
10108  try
10109  {
10110  while (idx < rules.Length)
10111  {
10112  ++rulesParsed;
10113  int code = rules.GetLSLIntegerItem(idx++);
10114 
10115  int remain = rules.Length - idx;
10116  idxStart = idx;
10117 
10118  switch (code)
10119  {
10120  case ScriptBaseClass.PRIM_POSITION:
10121  case ScriptBaseClass.PRIM_POS_LOCAL:
10122  if (remain < 1)
10123  return new LSL_List();
10124 
10125  try
10126  {
10127  sp.OffsetPosition = rules.GetVector3Item(idx++);
10128  }
10129  catch(InvalidCastException)
10130  {
10131  if (code == ScriptBaseClass.PRIM_POSITION)
10132  {
10133  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
10134  }
10135  else
10136  {
10137  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
10138  }
10139  return new LSL_List();
10140  }
10141  break;
10142 
10143  case ScriptBaseClass.PRIM_ROTATION:
10144  if (remain < 1)
10145  return new LSL_List();
10146 
10147  Quaternion inRot;
10148 
10149  try
10150  {
10151  inRot = rules.GetQuaternionItem(idx++);
10152  }
10153  catch(InvalidCastException)
10154  {
10155  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
10156  return new LSL_List();
10157  }
10158 
10159  SceneObjectPart parentPart = sp.ParentPart;
10160 
10161  if (parentPart != null)
10162  sp.Rotation = m_host.GetWorldRotation() * inRot;
10163 
10164  break;
10165 
10166  case ScriptBaseClass.PRIM_ROT_LOCAL:
10167  if (remain < 1)
10168  return new LSL_List();
10169 
10170  try
10171  {
10172  sp.Rotation = rules.GetQuaternionItem(idx++);
10173  }
10174  catch(InvalidCastException)
10175  {
10176  Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
10177  return new LSL_List();
10178  }
10179 
10180  break;
10181 
10182  case ScriptBaseClass.PRIM_TYPE:
10183  Error(originFunc, "PRIM_TYPE disallowed on agent");
10184  return new LSL_List();
10185 
10186  case ScriptBaseClass.PRIM_OMEGA:
10187  Error(originFunc, "PRIM_OMEGA disallowed on agent");
10188  return new LSL_List();
10189 
10190  case ScriptBaseClass.PRIM_LINK_TARGET:
10191  if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
10192  return new LSL_List();
10193 
10194  return rules.GetSublist(idx, -1);
10195 
10196  default:
10197  Error(originFunc,
10198  string.Format("Error running rule #{0} on agent: arg #{1} - disallowed on agent", rulesParsed, idx - idxStart));
10199  return new LSL_List();
10200  }
10201  }
10202  }
10203  catch (InvalidCastException e)
10204  {
10205  Error(
10206  originFunc,
10207  string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message);
10208  }
10209 
10210  return new LSL_List();
10211  }
10212 
10213  public LSL_String llStringToBase64(string str)
10214  {
10215  m_host.AddScriptLPS(1);
10216  try
10217  {
10218  byte[] encData_byte;
10219  encData_byte = Util.UTF8.GetBytes(str);
10220  string encodedData = Convert.ToBase64String(encData_byte);
10221  return encodedData;
10222  }
10223  catch
10224  {
10225  Error("llBase64ToString", "Error encoding string");
10226  return String.Empty;
10227  }
10228  }
10229 
10230  public LSL_String llBase64ToString(string str)
10231  {
10232  m_host.AddScriptLPS(1);
10233  try
10234  {
10235  byte[] b = Convert.FromBase64String(str);
10236  return Encoding.UTF8.GetString(b);
10237  }
10238  catch
10239  {
10240  Error("llBase64ToString", "Error decoding string");
10241  return String.Empty;
10242  }
10243  }
10244 
10245  public LSL_String llXorBase64Strings(string str1, string str2)
10246  {
10247  int padding = 0;
10248 
10249  string b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
10250 
10251  ScriptSleep(300);
10252  m_host.AddScriptLPS(1);
10253 
10254  if (str1 == String.Empty)
10255  return String.Empty;
10256  if (str2 == String.Empty)
10257  return str1;
10258 
10259  int len = str2.Length;
10260  if ((len % 4) != 0) // LL is EVIL!!!!
10261  {
10262  while (str2.EndsWith("="))
10263  str2 = str2.Substring(0, str2.Length - 1);
10264 
10265  len = str2.Length;
10266  int mod = len % 4;
10267 
10268  if (mod == 1)
10269  str2 = str2.Substring(0, str2.Length - 1);
10270  else if (mod == 2)
10271  str2 += "==";
10272  else if (mod == 3)
10273  str2 += "=";
10274  }
10275 
10276  byte[] data1;
10277  byte[] data2;
10278  try
10279  {
10280  data1 = Convert.FromBase64String(str1);
10281  data2 = Convert.FromBase64String(str2);
10282  }
10283  catch (Exception)
10284  {
10285  return new LSL_String(String.Empty);
10286  }
10287 
10288  // For cases where the decoded length of s2 is greater
10289  // than the decoded length of s1, simply perform a normal
10290  // decode and XOR
10291  //
10292  /*
10293  if (data2.Length >= data1.Length)
10294  {
10295  for (int pos = 0 ; pos < data1.Length ; pos++ )
10296  data1[pos] ^= data2[pos];
10297 
10298  return Convert.ToBase64String(data1);
10299  }
10300  */
10301 
10302  // Remove padding
10303  while (str1.EndsWith("="))
10304  {
10305  str1 = str1.Substring(0, str1.Length - 1);
10306  padding++;
10307  }
10308  while (str2.EndsWith("="))
10309  str2 = str2.Substring(0, str2.Length - 1);
10310 
10311  byte[] d1 = new byte[str1.Length];
10312  byte[] d2 = new byte[str2.Length];
10313 
10314  for (int i = 0 ; i < str1.Length ; i++)
10315  {
10316  int idx = b64.IndexOf(str1.Substring(i, 1));
10317  if (idx == -1)
10318  idx = 0;
10319  d1[i] = (byte)idx;
10320  }
10321 
10322  for (int i = 0 ; i < str2.Length ; i++)
10323  {
10324  int idx = b64.IndexOf(str2.Substring(i, 1));
10325  if (idx == -1)
10326  idx = 0;
10327  d2[i] = (byte)idx;
10328  }
10329 
10330  string output = String.Empty;
10331 
10332  for (int pos = 0 ; pos < d1.Length ; pos++)
10333  output += b64[d1[pos] ^ d2[pos % d2.Length]];
10334 
10335  // Here's a funny thing: LL blithely violate the base64
10336  // standard pretty much everywhere. Here, padding is
10337  // added only if the first input string had it, rather
10338  // than when the data actually needs it. This can result
10339  // in invalid base64 being returned. Go figure.
10340 
10341  while (padding-- > 0)
10342  output += "=";
10343 
10344  return output;
10345  }
10346 
10348  {
10349  m_host.AddScriptLPS(1);
10350  Deprecated("llRemoteDataSetRegion", "Use llOpenRemoteDataChannel instead");
10351  }
10352 
10353  public LSL_Float llLog10(double val)
10354  {
10355  m_host.AddScriptLPS(1);
10356  return (double)Math.Log10(val);
10357  }
10358 
10359  public LSL_Float llLog(double val)
10360  {
10361  m_host.AddScriptLPS(1);
10362  return (double)Math.Log(val);
10363  }
10364 
10365  public LSL_List llGetAnimationList(string id)
10366  {
10367  m_host.AddScriptLPS(1);
10368 
10369  LSL_List l = new LSL_List();
10370  ScenePresence av = World.GetScenePresence((UUID)id);
10371  if (av == null || av.IsChildAgent) // only if in the region
10372  return l;
10373  UUID[] anims;
10374  anims = av.Animator.GetAnimationArray();
10375  foreach (UUID foo in anims)
10376  l.Add(new LSL_Key(foo.ToString()));
10377  return l;
10378  }
10379 
10380  public void llSetParcelMusicURL(string url)
10381  {
10382  m_host.AddScriptLPS(1);
10383 
10384  ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
10385 
10386  if (land.LandData.OwnerID != m_host.OwnerID)
10387  return;
10388 
10389  land.SetMusicUrl(url);
10390 
10391  ScriptSleep(m_sleepMsOnSetParcelMusicURL);
10392  }
10393 
10395  {
10396  m_host.AddScriptLPS(1);
10397 
10398  ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
10399 
10400  if (land.LandData.OwnerID != m_host.OwnerID)
10401  return String.Empty;
10402 
10403  return land.GetMusicUrl();
10404  }
10405 
10407  {
10408  m_host.AddScriptLPS(1);
10409 
10410  return new LSL_Vector(m_host.ParentGroup.AbsolutePosition);
10411  }
10412 
10423  {
10424  m_host.AddScriptLPS(1);
10425  Quaternion q;
10426  if (m_host.ParentGroup.AttachmentPoint != 0)
10427  {
10428  ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
10429  if (avatar != null)
10430  if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
10431  q = avatar.CameraRotation; // Mouselook
10432  else
10433  q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate
10434  else
10435  q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case
10436  }
10437  else
10438  q = m_host.ParentGroup.GroupRotation; // just the group rotation
10439 
10440  return new LSL_Rotation(q);
10441  }
10442 
10444  {
10445  return m_host.Description!=null?m_host.Description:String.Empty;
10446  }
10447 
10448  public void llSetObjectDesc(string desc)
10449  {
10450  m_host.AddScriptLPS(1);
10451  m_host.Description = desc!=null?desc:String.Empty;
10452  }
10453 
10455  {
10456  m_host.AddScriptLPS(1);
10457  return m_host.CreatorID.ToString();
10458  }
10459 
10461  {
10462  m_host.AddScriptLPS(1);
10463  return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
10464  }
10465 
10467  {
10468  m_host.AddScriptLPS(1);
10469 
10470  return m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount();
10471  }
10472 
10484  public LSL_List llGetBoundingBox(string obj)
10485  {
10486  m_host.AddScriptLPS(1);
10487  UUID objID = UUID.Zero;
10488  LSL_List result = new LSL_List();
10489 
10490  // If the ID is not valid, return null result
10491  if (!UUID.TryParse(obj, out objID))
10492  {
10493  result.Add(new LSL_Vector());
10494  result.Add(new LSL_Vector());
10495  return result;
10496  }
10497 
10498  // Check if this is an attached prim. If so, replace
10499  // the UUID with the avatar UUID and report it's bounding box
10500  SceneObjectPart part = World.GetSceneObjectPart(objID);
10501  if (part != null && part.ParentGroup.IsAttachment)
10502  objID = part.ParentGroup.AttachedAvatar;
10503 
10504  // Find out if this is an avatar ID. If so, return it's box
10505  ScenePresence presence = World.GetScenePresence(objID);
10506  if (presence != null)
10507  {
10508  // As per LSL Wiki, there is no difference between sitting
10509  // and standing avatar since server 1.36
10510  LSL_Vector lower;
10511  LSL_Vector upper;
10512 
10513  Vector3 box = presence.Appearance.AvatarBoxSize * 0.5f;
10514 
10515  if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
10516  == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
10517 /*
10518  {
10519  // This is for ground sitting avatars
10520  float height = presence.Appearance.AvatarHeight / 2.66666667f;
10521  lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
10522  upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
10523  }
10524  else
10525  {
10526  // This is for standing/flying avatars
10527  float height = presence.Appearance.AvatarHeight / 2.0f;
10528  lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
10529  upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
10530  }
10531 
10532  // Adjust to the documented error offsets (see LSL Wiki)
10533  lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
10534  upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
10535 */
10536  {
10537  // This is for ground sitting avatars TODO!
10538  lower = new LSL_Vector(-box.X - 0.1125, -box.Y, box.Z * -1.0f);
10539  upper = new LSL_Vector(box.X + 0.1125, box.Y, box.Z * -1.0f);
10540  }
10541  else
10542  {
10543  // This is for standing/flying avatars
10544  lower = new LSL_Vector(-box.X, -box.Y, -box.Z);
10545  upper = new LSL_Vector(box.X, box.Y, box.Z);
10546  }
10547 
10548  if (lower.x > upper.x)
10549  lower.x = upper.x;
10550  if (lower.y > upper.y)
10551  lower.y = upper.y;
10552  if (lower.z > upper.z)
10553  lower.z = upper.z;
10554 
10555  result.Add(lower);
10556  result.Add(upper);
10557  return result;
10558  }
10559 
10560  part = World.GetSceneObjectPart(objID);
10561  // Currently only works for single prims without a sitting avatar
10562  if (part != null)
10563  {
10564  float minX;
10565  float maxX;
10566  float minY;
10567  float maxY;
10568  float minZ;
10569  float maxZ;
10570 
10571  // This BBox is in sim coordinates, with the offset being
10572  // a contained point.
10573  Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
10574  out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
10575 
10576  minX -= offsets[0].X;
10577  maxX -= offsets[0].X;
10578  minY -= offsets[0].Y;
10579  maxY -= offsets[0].Y;
10580  minZ -= offsets[0].Z;
10581  maxZ -= offsets[0].Z;
10582 
10583  LSL_Vector lower;
10584  LSL_Vector upper;
10585 
10586  // Adjust to the documented error offsets (see LSL Wiki)
10587  lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
10588  upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
10589 
10590  if (lower.x > upper.x)
10591  lower.x = upper.x;
10592  if (lower.y > upper.y)
10593  lower.y = upper.y;
10594  if (lower.z > upper.z)
10595  lower.z = upper.z;
10596 
10597  result.Add(lower);
10598  result.Add(upper);
10599  return result;
10600  }
10601 
10602  // Not found so return empty values
10603  result.Add(new LSL_Vector());
10604  result.Add(new LSL_Vector());
10605  return result;
10606  }
10607 
10611  private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper)
10612  {
10613  // Adjust from OS model
10614  // avatar height = visual height - 0.2, bounding box height = visual height
10615  // to SL model
10616  // avatar height = visual height, bounding box height = visual height + 0.2
10617  float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection;
10618 
10619  // According to avatar bounding box in SL 2015-04-18:
10620  // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h>
10621  // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5>
10622  // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h>
10623 
10624  // When avatar is sitting
10625  if (sp.ParentPart != null)
10626  {
10627  lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height);
10628  upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height);
10629  }
10630  // When avatar is groundsitting
10631  else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
10632  {
10633  lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height);
10634  upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height);
10635  }
10636  // When avatar is standing or flying
10637  else
10638  {
10639  lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height);
10640  upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height);
10641  }
10642  }
10643 
10644 
10646  {
10647  return new LSL_Vector(m_host.GetGeometricCenter());
10648  }
10649 
10651  {
10652  m_host.AddScriptLPS(1);
10653 
10654  LSL_List result = new LSL_List();
10655 
10656  LSL_List remaining = GetPrimParams(m_host, rules, ref result);
10657 
10658  while ((object)remaining != null && remaining.Length > 2)
10659  {
10660  int linknumber = remaining.GetLSLIntegerItem(0);
10661  rules = remaining.GetSublist(1, -1);
10662  List<SceneObjectPart> parts = GetLinkParts(linknumber);
10663 
10664  foreach (SceneObjectPart part in parts)
10665  remaining = GetPrimParams(part, rules, ref result);
10666  }
10667 
10668  return result;
10669  }
10670 
10671  public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
10672  {
10673  m_host.AddScriptLPS(1);
10674 
10675  // acording to SL wiki this must indicate a single link number or link_root or link_this.
10676  // keep other options as before
10677 
10678  List<SceneObjectPart> parts;
10679  List<ScenePresence> avatars;
10680 
10681  LSL_List res = new LSL_List();
10682  LSL_List remaining = new LSL_List();
10683 
10684  while (rules.Length > 0)
10685  {
10686  parts = GetLinkParts(linknumber);
10687  avatars = GetLinkAvatars(linknumber);
10688 
10689  remaining = new LSL_List();
10690  foreach (SceneObjectPart part in parts)
10691  {
10692  remaining = GetPrimParams(part, rules, ref res);
10693  }
10694  foreach (ScenePresence avatar in avatars)
10695  {
10696  remaining = GetPrimParams(avatar, rules, ref res);
10697  }
10698 
10699  if (remaining.Length > 0)
10700  {
10701  linknumber = remaining.GetLSLIntegerItem(0);
10702  rules = remaining.GetSublist(1, -1);
10703  }
10704  else
10705  break;
10706  }
10707 
10708  return res;
10709  }
10710 
10711  public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
10712  {
10713  int idx = 0;
10714  while (idx < rules.Length)
10715  {
10716  int code = (int)rules.GetLSLIntegerItem(idx++);
10717  int remain = rules.Length - idx;
10718 
10719  switch (code)
10720  {
10721  case (int)ScriptBaseClass.PRIM_MATERIAL:
10722  res.Add(new LSL_Integer(part.Material));
10723  break;
10724 
10725  case (int)ScriptBaseClass.PRIM_PHYSICS:
10726  if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0)
10727  res.Add(new LSL_Integer(1));
10728  else
10729  res.Add(new LSL_Integer(0));
10730  break;
10731 
10732  case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
10733  if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0)
10734  res.Add(new LSL_Integer(1));
10735  else
10736  res.Add(new LSL_Integer(0));
10737  break;
10738 
10739  case (int)ScriptBaseClass.PRIM_PHANTOM:
10740  if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
10741  res.Add(new LSL_Integer(1));
10742  else
10743  res.Add(new LSL_Integer(0));
10744  break;
10745 
10746  case (int)ScriptBaseClass.PRIM_POSITION:
10747  LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
10748  part.AbsolutePosition.Y,
10749  part.AbsolutePosition.Z);
10750  res.Add(v);
10751  break;
10752 
10753  case (int)ScriptBaseClass.PRIM_SIZE:
10754  res.Add(new LSL_Vector(part.Scale));
10755  break;
10756 
10757  case (int)ScriptBaseClass.PRIM_ROTATION:
10758  res.Add(GetPartRot(part));
10759  break;
10760 
10761  case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
10762  res.Add(new LSL_Integer((int)part.PhysicsShapeType));
10763  break;
10764 
10765  case (int)ScriptBaseClass.PRIM_TYPE:
10766  // implementing box
10767  PrimitiveBaseShape Shape = part.Shape;
10768  int primType = (int)part.GetPrimType();
10769  res.Add(new LSL_Integer(primType));
10770  double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX
10771  double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY.
10772  switch (primType)
10773  {
10774  case ScriptBaseClass.PRIM_TYPE_BOX:
10775  case ScriptBaseClass.PRIM_TYPE_CYLINDER:
10776  case ScriptBaseClass.PRIM_TYPE_PRISM:
10777  res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
10778  res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
10779  res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
10780  res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
10781  res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
10782  res.Add(new LSL_Vector(topshearx, topsheary, 0));
10783  break;
10784 
10785  case ScriptBaseClass.PRIM_TYPE_SPHERE:
10786  res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
10787  res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
10788  res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
10789  res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
10790  res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
10791  break;
10792 
10793  case ScriptBaseClass.PRIM_TYPE_SCULPT:
10794  res.Add(new LSL_String(Shape.SculptTexture.ToString()));
10795  res.Add(new LSL_Integer(Shape.SculptType));
10796  break;
10797 
10798  case ScriptBaseClass.PRIM_TYPE_RING:
10799  case ScriptBaseClass.PRIM_TYPE_TUBE:
10800  case ScriptBaseClass.PRIM_TYPE_TORUS:
10801  // holeshape
10802  res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
10803 
10804  // cut
10805  res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
10806 
10807  // hollow
10808  res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
10809 
10810  // twist
10811  res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
10812 
10813  // vector holesize
10814  res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
10815 
10816  // vector topshear
10817  res.Add(new LSL_Vector(topshearx, topsheary, 0));
10818 
10819  // vector profilecut
10820  res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
10821 
10822  // vector tapera
10823  res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
10824 
10825  // float revolutions
10826  res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
10827  // Slightly inaccurate, because an unsigned byte is being used to represent
10828  // the entire range of floating-point values from 1.0 through 4.0 (which is how
10829  // SL does it).
10830  //
10831  // Using these formulas to store and retrieve PathRevolutions, it is not
10832  // possible to use all values between 1.00 and 4.00. For instance, you can't
10833  // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
10834  // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
10835  // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
10836  // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
10837  // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
10838  // such as 1.10. So, SL must store and retreive the actual user input rather
10839  // than only storing the encoded value.
10840 
10841  // float radiusoffset
10842  res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
10843 
10844  // float skew
10845  res.Add(new LSL_Float(Shape.PathSkew / 100.0));
10846  break;
10847  }
10848  break;
10849 
10850  case (int)ScriptBaseClass.PRIM_TEXTURE:
10851  if (remain < 1)
10852  return new LSL_List();
10853 
10854  int face = (int)rules.GetLSLIntegerItem(idx++);
10855  Primitive.TextureEntry tex = part.Shape.Textures;
10856  if (face == ScriptBaseClass.ALL_SIDES)
10857  {
10858  for (face = 0; face < GetNumberOfSides(part); face++)
10859  {
10860  Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10861 
10862  res.Add(new LSL_String(texface.TextureID.ToString()));
10863  res.Add(new LSL_Vector(texface.RepeatU,
10864  texface.RepeatV,
10865  0));
10866  res.Add(new LSL_Vector(texface.OffsetU,
10867  texface.OffsetV,
10868  0));
10869  res.Add(new LSL_Float(texface.Rotation));
10870  }
10871  }
10872  else
10873  {
10874  if (face >= 0 && face < GetNumberOfSides(part))
10875  {
10876  Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10877 
10878  res.Add(new LSL_String(texface.TextureID.ToString()));
10879  res.Add(new LSL_Vector(texface.RepeatU,
10880  texface.RepeatV,
10881  0));
10882  res.Add(new LSL_Vector(texface.OffsetU,
10883  texface.OffsetV,
10884  0));
10885  res.Add(new LSL_Float(texface.Rotation));
10886  }
10887  }
10888  break;
10889 
10890  case (int)ScriptBaseClass.PRIM_COLOR:
10891  if (remain < 1)
10892  return new LSL_List();
10893 
10894  face = (int)rules.GetLSLIntegerItem(idx++);
10895 
10896  tex = part.Shape.Textures;
10897  Color4 texcolor;
10898  if (face == ScriptBaseClass.ALL_SIDES)
10899  {
10900  for (face = 0; face < GetNumberOfSides(part); face++)
10901  {
10902  texcolor = tex.GetFace((uint)face).RGBA;
10903  res.Add(new LSL_Vector(texcolor.R,
10904  texcolor.G,
10905  texcolor.B));
10906  res.Add(new LSL_Float(texcolor.A));
10907  }
10908  }
10909  else
10910  {
10911  texcolor = tex.GetFace((uint)face).RGBA;
10912  res.Add(new LSL_Vector(texcolor.R,
10913  texcolor.G,
10914  texcolor.B));
10915  res.Add(new LSL_Float(texcolor.A));
10916  }
10917  break;
10918 
10919  case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
10920  if (remain < 1)
10921  return new LSL_List();
10922 
10923  face = (int)rules.GetLSLIntegerItem(idx++);
10924 
10925  tex = part.Shape.Textures;
10926  int shiny;
10927  if (face == ScriptBaseClass.ALL_SIDES)
10928  {
10929  for (face = 0; face < GetNumberOfSides(part); face++)
10930  {
10931  Shininess shinyness = tex.GetFace((uint)face).Shiny;
10932  if (shinyness == Shininess.High)
10933  {
10934  shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
10935  }
10936  else if (shinyness == Shininess.Medium)
10937  {
10938  shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
10939  }
10940  else if (shinyness == Shininess.Low)
10941  {
10942  shiny = ScriptBaseClass.PRIM_SHINY_LOW;
10943  }
10944  else
10945  {
10946  shiny = ScriptBaseClass.PRIM_SHINY_NONE;
10947  }
10948  res.Add(new LSL_Integer(shiny));
10949  res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
10950  }
10951  }
10952  else
10953  {
10954  Shininess shinyness = tex.GetFace((uint)face).Shiny;
10955  if (shinyness == Shininess.High)
10956  {
10957  shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
10958  }
10959  else if (shinyness == Shininess.Medium)
10960  {
10961  shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
10962  }
10963  else if (shinyness == Shininess.Low)
10964  {
10965  shiny = ScriptBaseClass.PRIM_SHINY_LOW;
10966  }
10967  else
10968  {
10969  shiny = ScriptBaseClass.PRIM_SHINY_NONE;
10970  }
10971  res.Add(new LSL_Integer(shiny));
10972  res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
10973  }
10974  break;
10975 
10976  case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
10977  if (remain < 1)
10978  return new LSL_List();
10979 
10980  face = (int)rules.GetLSLIntegerItem(idx++);
10981 
10982  tex = part.Shape.Textures;
10983  int fullbright;
10984  if (face == ScriptBaseClass.ALL_SIDES)
10985  {
10986  for (face = 0; face < GetNumberOfSides(part); face++)
10987  {
10988  if (tex.GetFace((uint)face).Fullbright == true)
10989  {
10990  fullbright = ScriptBaseClass.TRUE;
10991  }
10992  else
10993  {
10994  fullbright = ScriptBaseClass.FALSE;
10995  }
10996  res.Add(new LSL_Integer(fullbright));
10997  }
10998  }
10999  else
11000  {
11001  if (tex.GetFace((uint)face).Fullbright == true)
11002  {
11003  fullbright = ScriptBaseClass.TRUE;
11004  }
11005  else
11006  {
11007  fullbright = ScriptBaseClass.FALSE;
11008  }
11009  res.Add(new LSL_Integer(fullbright));
11010  }
11011  break;
11012 
11013  case (int)ScriptBaseClass.PRIM_FLEXIBLE:
11014  PrimitiveBaseShape shape = part.Shape;
11015 
11016  if (shape.FlexiEntry)
11017  res.Add(new LSL_Integer(1)); // active
11018  else
11019  res.Add(new LSL_Integer(0));
11020  res.Add(new LSL_Integer(shape.FlexiSoftness));// softness
11021  res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
11022  res.Add(new LSL_Float(shape.FlexiDrag)); // friction
11023  res.Add(new LSL_Float(shape.FlexiWind)); // wind
11024  res.Add(new LSL_Float(shape.FlexiTension)); // tension
11025  res.Add(new LSL_Vector(shape.FlexiForceX, // force
11026  shape.FlexiForceY,
11027  shape.FlexiForceZ));
11028  break;
11029 
11030  case (int)ScriptBaseClass.PRIM_TEXGEN:
11031  // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
11032  if (remain < 1)
11033  return new LSL_List();
11034 
11035  face = (int)rules.GetLSLIntegerItem(idx++);
11036 
11037  tex = part.Shape.Textures;
11038  if (face == ScriptBaseClass.ALL_SIDES)
11039  {
11040  for (face = 0; face < GetNumberOfSides(part); face++)
11041  {
11042  if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
11043  {
11045  }
11046  else
11047  {
11049  }
11050  }
11051  }
11052  else
11053  {
11054  if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
11055  {
11057  }
11058  else
11059  {
11061  }
11062  }
11063  break;
11064 
11065  case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
11066  shape = part.Shape;
11067 
11068  if (shape.LightEntry)
11069  res.Add(new LSL_Integer(1)); // active
11070  else
11071  res.Add(new LSL_Integer(0));
11072  res.Add(new LSL_Vector(shape.LightColorR, // color
11073  shape.LightColorG,
11074  shape.LightColorB));
11075  res.Add(new LSL_Float(shape.LightIntensity)); // intensity
11076  res.Add(new LSL_Float(shape.LightRadius)); // radius
11077  res.Add(new LSL_Float(shape.LightFalloff)); // falloff
11078  break;
11079 
11080  case (int)ScriptBaseClass.PRIM_GLOW:
11081  if (remain < 1)
11082  return new LSL_List();
11083 
11084  face = (int)rules.GetLSLIntegerItem(idx++);
11085 
11086  tex = part.Shape.Textures;
11087  float primglow;
11088  if (face == ScriptBaseClass.ALL_SIDES)
11089  {
11090  for (face = 0; face < GetNumberOfSides(part); face++)
11091  {
11092  primglow = tex.GetFace((uint)face).Glow;
11093  res.Add(new LSL_Float(primglow));
11094  }
11095  }
11096  else
11097  {
11098  primglow = tex.GetFace((uint)face).Glow;
11099  res.Add(new LSL_Float(primglow));
11100  }
11101  break;
11102 
11103  case (int)ScriptBaseClass.PRIM_TEXT:
11104  Color4 textColor = part.GetTextColor();
11105  res.Add(new LSL_String(part.Text));
11106  res.Add(new LSL_Vector(textColor.R,
11107  textColor.G,
11108  textColor.B));
11109  res.Add(new LSL_Float(textColor.A));
11110  break;
11111 
11112  case (int)ScriptBaseClass.PRIM_NAME:
11113  res.Add(new LSL_String(part.Name));
11114  break;
11115 
11116  case (int)ScriptBaseClass.PRIM_DESC:
11117  res.Add(new LSL_String(part.Description));
11118  break;
11119  case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
11120  res.Add(new LSL_Rotation(part.RotationOffset));
11121  break;
11122 
11123  case (int)ScriptBaseClass.PRIM_POS_LOCAL:
11124  res.Add(new LSL_Vector(GetPartLocalPos(part)));
11125  break;
11126  case (int)ScriptBaseClass.PRIM_SLICE:
11127  PrimType prim_type = part.GetPrimType();
11128  bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING);
11129  res.Add(new LSL_Vector(
11130  (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0,
11131  1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0,
11132  0
11133  ));
11134  break;
11135  case (int)ScriptBaseClass.PRIM_LINK_TARGET:
11136 
11137  // TODO: Should be issuing a runtime script warning in this case.
11138  if (remain < 2)
11139  return new LSL_List();
11140 
11141  return rules.GetSublist(idx, -1);
11142  }
11143  }
11144 
11145  return new LSL_List();
11146  }
11147 
11148 
11149  public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
11150  {
11151  m_host.AddScriptLPS(1);
11152  ScriptSleep(m_sleepMsOnGetPrimMediaParams);
11153  return GetPrimMediaParams(m_host, face, rules);
11154  }
11155 
11157  {
11158  m_host.AddScriptLPS(1);
11159  ScriptSleep(m_sleepMsOnGetLinkMedia);
11160  if (link == ScriptBaseClass.LINK_ROOT)
11161  return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules);
11162  else if (link == ScriptBaseClass.LINK_THIS)
11163  return GetPrimMediaParams(m_host, face, rules);
11164  else
11165  {
11166  SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link);
11167  if (null != part)
11168  return GetPrimMediaParams(part, face, rules);
11169  }
11170 
11171  return new LSL_List();
11172  }
11173 
11174  private LSL_List GetPrimMediaParams(SceneObjectPart part, int face, LSL_List rules)
11175  {
11176  // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
11177  // TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
11178  // Assuming silently fail means give back an empty list. Ideally, need to check this.
11179  if (face < 0 || face > part.GetNumberOfSides() - 1)
11180  return new LSL_List();
11181 
11182  IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
11183  if (null == module)
11184  return new LSL_List();
11185 
11186  MediaEntry me = module.GetMediaEntry(part, face);
11187 
11188  // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
11189  if (null == me)
11190  return new LSL_List();
11191 
11192  LSL_List res = new LSL_List();
11193 
11194  for (int i = 0; i < rules.Length; i++)
11195  {
11196  int code = (int)rules.GetLSLIntegerItem(i);
11197 
11198  switch (code)
11199  {
11200  case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
11201  // Not implemented
11202  res.Add(new LSL_Integer(0));
11203  break;
11204 
11205  case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
11206  if (me.Controls == MediaControls.Standard)
11208  else
11210  break;
11211 
11212  case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
11213  res.Add(new LSL_String(me.CurrentURL));
11214  break;
11215 
11216  case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
11217  res.Add(new LSL_String(me.HomeURL));
11218  break;
11219 
11220  case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
11221  res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
11222  break;
11223 
11224  case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
11225  res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
11226  break;
11227 
11228  case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
11229  res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
11230  break;
11231 
11232  case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
11233  res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
11234  break;
11235 
11236  case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
11237  res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
11238  break;
11239 
11240  case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
11241  res.Add(new LSL_Integer(me.Width));
11242  break;
11243 
11244  case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
11245  res.Add(new LSL_Integer(me.Height));
11246  break;
11247 
11248  case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
11249  res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
11250  break;
11251 
11252  case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
11253  string[] urls = (string[])me.WhiteList.Clone();
11254 
11255  for (int j = 0; j < urls.Length; j++)
11256  urls[j] = Uri.EscapeDataString(urls[j]);
11257 
11258  res.Add(new LSL_String(string.Join(", ", urls)));
11259  break;
11260 
11261  case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
11262  res.Add(new LSL_Integer((int)me.InteractPermissions));
11263  break;
11264 
11265  case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
11266  res.Add(new LSL_Integer((int)me.ControlPermissions));
11267  break;
11268 
11269  default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS;
11270  }
11271  }
11272 
11273  return res;
11274  }
11275 
11277  {
11278  m_host.AddScriptLPS(1);
11279  ScriptSleep(m_sleepMsOnSetPrimMediaParams);
11280  return SetPrimMediaParams(m_host, face, rules);
11281  }
11282 
11284  {
11285  m_host.AddScriptLPS(1);
11286  ScriptSleep(m_sleepMsOnSetLinkMedia);
11287  if (link == ScriptBaseClass.LINK_ROOT)
11288  return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules);
11289  else if (link == ScriptBaseClass.LINK_THIS)
11290  return SetPrimMediaParams(m_host, face, rules);
11291  else
11292  {
11293  SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link);
11294  if (null != part)
11295  return SetPrimMediaParams(part, face, rules);
11296  }
11297 
11298  return ScriptBaseClass.LSL_STATUS_NOT_FOUND;
11299  }
11300 
11301  private LSL_Integer SetPrimMediaParams(SceneObjectPart part, LSL_Integer face, LSL_List rules)
11302  {
11303  // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
11304  // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
11305  // Don't perform the media check directly
11306  if (face < 0 || face > part.GetNumberOfSides() - 1)
11308 
11309  IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
11310  if (null == module)
11311  return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED;
11312 
11313  MediaEntry me = module.GetMediaEntry(part, face);
11314  if (null == me)
11315  me = new MediaEntry();
11316 
11317  int i = 0;
11318 
11319  while (i < rules.Length - 1)
11320  {
11321  int code = rules.GetLSLIntegerItem(i++);
11322 
11323  switch (code)
11324  {
11325  case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
11326  me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false);
11327  break;
11328 
11329  case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
11330  int v = rules.GetLSLIntegerItem(i++);
11332  me.Controls = MediaControls.Standard;
11333  else
11334  me.Controls = MediaControls.Mini;
11335  break;
11336 
11337  case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
11338  me.CurrentURL = rules.GetLSLStringItem(i++);
11339  break;
11340 
11341  case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
11342  me.HomeURL = rules.GetLSLStringItem(i++);
11343  break;
11344 
11345  case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
11346  me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11347  break;
11348 
11349  case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
11350  me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11351  break;
11352 
11353  case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
11354  me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11355  break;
11356 
11357  case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
11358  me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11359  break;
11360 
11361  case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
11362  me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11363  break;
11364 
11365  case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
11366  me.Width = (int)rules.GetLSLIntegerItem(i++);
11367  break;
11368 
11369  case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
11370  me.Height = (int)rules.GetLSLIntegerItem(i++);
11371  break;
11372 
11373  case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
11374  me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11375  break;
11376 
11377  case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
11378  string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' });
11379  List<string> whiteListUrls = new List<string>();
11380  Array.ForEach(
11381  rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); });
11382  me.WhiteList = whiteListUrls.ToArray();
11383  break;
11384 
11385  case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
11386  me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
11387  break;
11388 
11389  case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
11390  me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
11391  break;
11392 
11393  default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS;
11394  }
11395  }
11396 
11397  module.SetMediaEntry(part, face, me);
11398 
11399  return ScriptBaseClass.LSL_STATUS_OK;
11400  }
11401 
11403  {
11404  m_host.AddScriptLPS(1);
11405  ScriptSleep(m_sleepMsOnClearPrimMedia);
11406  return ClearPrimMedia(m_host, face);
11407  }
11408 
11410  {
11411  m_host.AddScriptLPS(1);
11412  ScriptSleep(m_sleepMsOnClearLinkMedia);
11413  if (link == ScriptBaseClass.LINK_ROOT)
11414  return ClearPrimMedia(m_host.ParentGroup.RootPart, face);
11415  else if (link == ScriptBaseClass.LINK_THIS)
11416  return ClearPrimMedia(m_host, face);
11417  else
11418  {
11419  SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link);
11420  if (null != part)
11421  return ClearPrimMedia(part, face);
11422  }
11423 
11424  return ScriptBaseClass.LSL_STATUS_NOT_FOUND;
11425  }
11426 
11427  private LSL_Integer ClearPrimMedia(SceneObjectPart part, LSL_Integer face)
11428  {
11429  // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid
11430  // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
11431  // FIXME: Don't perform the media check directly
11432  if (face < 0 || face > part.GetNumberOfSides() - 1)
11434 
11435  IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
11436  if (null == module)
11437  return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED;
11438 
11439  module.ClearMediaEntry(part, face);
11440 
11441  return ScriptBaseClass.LSL_STATUS_OK;
11442  }
11443 
11444  // <remarks>
11445  // <para>
11446  // The .NET definition of base 64 is:
11447  // <list>
11448  // <item>
11449  // Significant: A-Z a-z 0-9 + -
11450  // </item>
11451  // <item>
11452  // Whitespace: \t \n \r ' '
11453  // </item>
11454  // <item>
11455  // Valueless: =
11456  // </item>
11457  // <item>
11458  // End-of-string: \0 or '=='
11459  // </item>
11460  // </list>
11461  // </para>
11462  // <para>
11463  // Each point in a base-64 string represents
11464  // a 6 bit value. A 32-bit integer can be
11465  // represented using 6 characters (with some
11466  // redundancy).
11467  // </para>
11468  // <para>
11469  // LSL requires a base64 string to be 8
11470  // characters in length. LSL also uses '/'
11471  // rather than '-' (MIME compliant).
11472  // </para>
11473  // <para>
11474  // RFC 1341 used as a reference (as specified
11475  // by the SecondLife Wiki).
11476  // </para>
11477  // <para>
11478  // SL do not record any kind of exception for
11479  // these functions, so the string to integer
11480  // conversion returns '0' if an invalid
11481  // character is encountered during conversion.
11482  // </para>
11483  // <para>
11484  // References
11485  // <list>
11486  // <item>
11487  // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
11488  // </item>
11489  // <item>
11490  // </item>
11491  // </list>
11492  // </para>
11493  // </remarks>
11494 
11495  // <summary>
11496  // Table for converting 6-bit integers into
11497  // base-64 characters
11498  // </summary>
11499 
11500  protected static readonly char[] i2ctable =
11501  {
11502  'A','B','C','D','E','F','G','H',
11503  'I','J','K','L','M','N','O','P',
11504  'Q','R','S','T','U','V','W','X',
11505  'Y','Z',
11506  'a','b','c','d','e','f','g','h',
11507  'i','j','k','l','m','n','o','p',
11508  'q','r','s','t','u','v','w','x',
11509  'y','z',
11510  '0','1','2','3','4','5','6','7',
11511  '8','9',
11512  '+','/'
11513  };
11514 
11515  // <summary>
11516  // Table for converting base-64 characters
11517  // into 6-bit integers.
11518  // </summary>
11519 
11520  protected static readonly int[] c2itable =
11521  {
11522  -1,-1,-1,-1,-1,-1,-1,-1, // 0x
11523  -1,-1,-1,-1,-1,-1,-1,-1,
11524  -1,-1,-1,-1,-1,-1,-1,-1, // 1x
11525  -1,-1,-1,-1,-1,-1,-1,-1,
11526  -1,-1,-1,-1,-1,-1,-1,-1, // 2x
11527  -1,-1,-1,63,-1,-1,-1,64,
11528  53,54,55,56,57,58,59,60, // 3x
11529  61,62,-1,-1,-1,0,-1,-1,
11530  -1,1,2,3,4,5,6,7, // 4x
11531  8,9,10,11,12,13,14,15,
11532  16,17,18,19,20,21,22,23, // 5x
11533  24,25,26,-1,-1,-1,-1,-1,
11534  -1,27,28,29,30,31,32,33, // 6x
11535  34,35,36,37,38,39,40,41,
11536  42,43,44,45,46,47,48,49, // 7x
11537  50,51,52,-1,-1,-1,-1,-1,
11538  -1,-1,-1,-1,-1,-1,-1,-1, // 8x
11539  -1,-1,-1,-1,-1,-1,-1,-1,
11540  -1,-1,-1,-1,-1,-1,-1,-1, // 9x
11541  -1,-1,-1,-1,-1,-1,-1,-1,
11542  -1,-1,-1,-1,-1,-1,-1,-1, // Ax
11543  -1,-1,-1,-1,-1,-1,-1,-1,
11544  -1,-1,-1,-1,-1,-1,-1,-1, // Bx
11545  -1,-1,-1,-1,-1,-1,-1,-1,
11546  -1,-1,-1,-1,-1,-1,-1,-1, // Cx
11547  -1,-1,-1,-1,-1,-1,-1,-1,
11548  -1,-1,-1,-1,-1,-1,-1,-1, // Dx
11549  -1,-1,-1,-1,-1,-1,-1,-1,
11550  -1,-1,-1,-1,-1,-1,-1,-1, // Ex
11551  -1,-1,-1,-1,-1,-1,-1,-1,
11552  -1,-1,-1,-1,-1,-1,-1,-1, // Fx
11553  -1,-1,-1,-1,-1,-1,-1,-1
11554  };
11555 
11556  // <summary>
11557  // Converts a 32-bit integer into a Base64
11558  // character string. Base64 character strings
11559  // are always 8 characters long. All iinteger
11560  // values are acceptable.
11561  // </summary>
11562  // <param name="number">
11563  // 32-bit integer to be converted.
11564  // </param>
11565  // <returns>
11566  // 8 character string. The 1st six characters
11567  // contain the encoded number, the last two
11568  // characters are padded with "=".
11569  // </returns>
11570 
11571  public LSL_String llIntegerToBase64(int number)
11572  {
11573  // uninitialized string
11574 
11575  char[] imdt = new char[8];
11576 
11577  m_host.AddScriptLPS(1);
11578 
11579  // Manually unroll the loop
11580 
11581  imdt[7] = '=';
11582  imdt[6] = '=';
11583  imdt[5] = i2ctable[number<<4 & 0x3F];
11584  imdt[4] = i2ctable[number>>2 & 0x3F];
11585  imdt[3] = i2ctable[number>>8 & 0x3F];
11586  imdt[2] = i2ctable[number>>14 & 0x3F];
11587  imdt[1] = i2ctable[number>>20 & 0x3F];
11588  imdt[0] = i2ctable[number>>26 & 0x3F];
11589 
11590  return new string(imdt);
11591  }
11592 
11593  // <summary>
11594  // Converts an eight character base-64 string
11595  // into a 32-bit integer.
11596  // </summary>
11597  // <param name="str">
11598  // 8 characters string to be converted. Other
11599  // length strings return zero.
11600  // </param>
11601  // <returns>
11602  // Returns an integer representing the
11603  // encoded value providedint he 1st 6
11604  // characters of the string.
11605  // </returns>
11606  // <remarks>
11607  // This is coded to behave like LSL's
11608  // implementation (I think), based upon the
11609  // information available at the Wiki.
11610  // If more than 8 characters are supplied,
11611  // zero is returned.
11612  // If a NULL string is supplied, zero will
11613  // be returned.
11614  // If fewer than 6 characters are supplied, then
11615  // the answer will reflect a partial
11616  // accumulation.
11617  // <para>
11618  // The 6-bit segments are
11619  // extracted left-to-right in big-endian mode,
11620  // which means that segment 6 only contains the
11621  // two low-order bits of the 32 bit integer as
11622  // its high order 2 bits. A short string therefore
11623  // means loss of low-order information. E.g.
11624  //
11625  // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
11626  // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
11627  // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
11628  // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
11629  // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
11630  //
11631  // </para>
11632  // </remarks>
11633 
11634  public LSL_Integer llBase64ToInteger(string str)
11635  {
11636  int number = 0;
11637  int digit;
11638 
11639  m_host.AddScriptLPS(1);
11640 
11641  // Require a well-fromed base64 string
11642 
11643  if (str.Length > 8)
11644  return 0;
11645 
11646  // The loop is unrolled in the interests
11647  // of performance and simple necessity.
11648  //
11649  // MUST find 6 digits to be well formed
11650  // -1 == invalid
11651  // 0 == padding
11652 
11653  if ((digit = c2itable[str[0]]) <= 0)
11654  {
11655  return digit < 0 ? (int)0 : number;
11656  }
11657  number += --digit<<26;
11658 
11659  if ((digit = c2itable[str[1]]) <= 0)
11660  {
11661  return digit < 0 ? (int)0 : number;
11662  }
11663  number += --digit<<20;
11664 
11665  if ((digit = c2itable[str[2]]) <= 0)
11666  {
11667  return digit < 0 ? (int)0 : number;
11668  }
11669  number += --digit<<14;
11670 
11671  if ((digit = c2itable[str[3]]) <= 0)
11672  {
11673  return digit < 0 ? (int)0 : number;
11674  }
11675  number += --digit<<8;
11676 
11677  if ((digit = c2itable[str[4]]) <= 0)
11678  {
11679  return digit < 0 ? (int)0 : number;
11680  }
11681  number += --digit<<2;
11682 
11683  if ((digit = c2itable[str[5]]) <= 0)
11684  {
11685  return digit < 0 ? (int)0 : number;
11686  }
11687  number += --digit>>4;
11688 
11689  // ignore trailing padding
11690 
11691  return number;
11692  }
11693 
11695  {
11696  m_host.AddScriptLPS(1);
11697  return DateTime.UtcNow.TimeOfDay.TotalSeconds;
11698  }
11699 
11700  public LSL_String llGetHTTPHeader(LSL_Key request_id, string header)
11701  {
11702  m_host.AddScriptLPS(1);
11703 
11704  if (m_UrlModule != null)
11705  return m_UrlModule.GetHttpHeader(new UUID(request_id), header);
11706  return String.Empty;
11707  }
11708 
11709 
11711  {
11712  m_host.AddScriptLPS(1);
11713  IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
11714  return UrlModule.ExternalHostNameForLSL;
11715  }
11716 
11717  // <summary>
11718  // Scan the string supplied in 'src' and
11719  // tokenize it based upon two sets of
11720  // tokenizers provided in two lists,
11721  // separators and spacers.
11722  // </summary>
11723  //
11724  // <remarks>
11725  // Separators demarcate tokens and are
11726  // elided as they are encountered. Spacers
11727  // also demarcate tokens, but are themselves
11728  // retained as tokens.
11729  //
11730  // Both separators and spacers may be arbitrarily
11731  // long strings. i.e. ":::".
11732  //
11733  // The function returns an ordered list
11734  // representing the tokens found in the supplied
11735  // sources string. If two successive tokenizers
11736  // are encountered, then a null-string entry is
11737  // added to the list.
11738  //
11739  // It is a precondition that the source and
11740  // toekizer lisst are non-null. If they are null,
11741  // then a null pointer exception will be thrown
11742  // while their lengths are being determined.
11743  //
11744  // A small amount of working memoryis required
11745  // of approximately 8*#tokenizers + 8*srcstrlen.
11746  //
11747  // There are many ways in which this function
11748  // can be implemented, this implementation is
11749  // fairly naive and assumes that when the
11750  // function is invooked with a short source
11751  // string and/or short lists of tokenizers, then
11752  // performance will not be an issue.
11753  //
11754  // In order to minimize the perofrmance
11755  // effects of long strings, or large numbers
11756  // of tokeizers, the function skips as far as
11757  // possible whenever a toekenizer is found,
11758  // and eliminates redundant tokenizers as soon
11759  // as is possible.
11760  //
11761  // The implementation tries to minimize temporary
11762  // garbage generation.
11763  // </remarks>
11764 
11765  public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
11766  {
11767  return ParseString2List(src, separators, spacers, true);
11768  }
11769 
11770  private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
11771  {
11772  int srclen = src.Length;
11773  int seplen = separators.Length;
11774  object[] separray = separators.Data;
11775  int spclen = spacers.Length;
11776  object[] spcarray = spacers.Data;
11777  int dellen = 0;
11778  string[] delarray = new string[seplen+spclen];
11779 
11780  int outlen = 0;
11781  string[] outarray = new string[srclen*2+1];
11782 
11783  int i, j;
11784  string d;
11785 
11786  m_host.AddScriptLPS(1);
11787 
11788  /*
11789  * Convert separator and spacer lists to C# strings.
11790  * Also filter out null strings so we don't hang.
11791  */
11792  for (i = 0; i < seplen; i ++)
11793  {
11794  d = separray[i].ToString();
11795  if (d.Length > 0)
11796  {
11797  delarray[dellen++] = d;
11798  }
11799  }
11800  seplen = dellen;
11801 
11802  for (i = 0; i < spclen; i ++)
11803  {
11804  d = spcarray[i].ToString();
11805  if (d.Length > 0)
11806  {
11807  delarray[dellen++] = d;
11808  }
11809  }
11810 
11811  /*
11812  * Scan through source string from beginning to end.
11813  */
11814  for (i = 0;;)
11815  {
11816 
11817  /*
11818  * Find earliest delimeter in src starting at i (if any).
11819  */
11820  int earliestDel = -1;
11821  int earliestSrc = srclen;
11822  string earliestStr = null;
11823  for (j = 0; j < dellen; j ++)
11824  {
11825  d = delarray[j];
11826  if (d != null)
11827  {
11828  int index = src.IndexOf(d, i);
11829  if (index < 0)
11830  {
11831  delarray[j] = null; // delim nowhere in src, don't check it anymore
11832  }
11833  else if (index < earliestSrc)
11834  {
11835  earliestSrc = index; // where delimeter starts in source string
11836  earliestDel = j; // where delimeter is in delarray[]
11837  earliestStr = d; // the delimeter string from delarray[]
11838  if (index == i) break; // can't do any better than found at beg of string
11839  }
11840  }
11841  }
11842 
11843  /*
11844  * Output source string starting at i through start of earliest delimeter.
11845  */
11846  if (keepNulls || (earliestSrc > i))
11847  {
11848  outarray[outlen++] = src.Substring(i, earliestSrc - i);
11849  }
11850 
11851  /*
11852  * If no delimeter found at or after i, we're done scanning.
11853  */
11854  if (earliestDel < 0) break;
11855 
11856  /*
11857  * If delimeter was a spacer, output the spacer.
11858  */
11859  if (earliestDel >= seplen)
11860  {
11861  outarray[outlen++] = earliestStr;
11862  }
11863 
11864  /*
11865  * Look at rest of src string following delimeter.
11866  */
11867  i = earliestSrc + earliestStr.Length;
11868  }
11869 
11870  /*
11871  * Make up an exact-sized output array suitable for an LSL_List object.
11872  */
11873  object[] outlist = new object[outlen];
11874  for (i = 0; i < outlen; i ++)
11875  {
11876  outlist[i] = new LSL_String(outarray[i]);
11877  }
11878  return new LSL_List(outlist);
11879  }
11880 
11882  {
11883  m_host.AddScriptLPS(1);
11884 
11885  int permmask = 0;
11886 
11887  if (mask == ScriptBaseClass.MASK_BASE)//0
11888  {
11889  permmask = (int)m_host.BaseMask;
11890  }
11891 
11892  else if (mask == ScriptBaseClass.MASK_OWNER)//1
11893  {
11894  permmask = (int)m_host.OwnerMask;
11895  }
11896 
11897  else if (mask == ScriptBaseClass.MASK_GROUP)//2
11898  {
11899  permmask = (int)m_host.GroupMask;
11900  }
11901 
11902  else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
11903  {
11904  permmask = (int)m_host.EveryoneMask;
11905  }
11906 
11907  else if (mask == ScriptBaseClass.MASK_NEXT)//4
11908  {
11909  permmask = (int)m_host.NextOwnerMask;
11910  }
11911 
11912  return permmask;
11913  }
11914 
11915  public void llSetObjectPermMask(int mask, int value)
11916  {
11917  m_host.AddScriptLPS(1);
11918 
11919  if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
11920  {
11921  if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
11922  {
11923  if (mask == ScriptBaseClass.MASK_BASE)//0
11924  {
11925  m_host.BaseMask = (uint)value;
11926  }
11927 
11928  else if (mask == ScriptBaseClass.MASK_OWNER)//1
11929  {
11930  m_host.OwnerMask = (uint)value;
11931  }
11932 
11933  else if (mask == ScriptBaseClass.MASK_GROUP)//2
11934  {
11935  m_host.GroupMask = (uint)value;
11936  }
11937 
11938  else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
11939  {
11940  m_host.EveryoneMask = (uint)value;
11941  }
11942 
11943  else if (mask == ScriptBaseClass.MASK_NEXT)//4
11944  {
11945  m_host.NextOwnerMask = (uint)value;
11946  }
11947  }
11948  }
11949  }
11950 
11951  public LSL_Integer llGetInventoryPermMask(string itemName, int mask)
11952  {
11953  m_host.AddScriptLPS(1);
11954 
11955  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
11956 
11957  if (item == null)
11958  return -1;
11959 
11960  switch (mask)
11961  {
11962  case 0:
11963  return (int)item.BasePermissions;
11964  case 1:
11965  return (int)item.CurrentPermissions;
11966  case 2:
11967  return (int)item.GroupPermissions;
11968  case 3:
11969  return (int)item.EveryonePermissions;
11970  case 4:
11971  return (int)item.NextPermissions;
11972  }
11973 
11974  return -1;
11975  }
11976 
11977  public void llSetInventoryPermMask(string itemName, int mask, int value)
11978  {
11979  m_host.AddScriptLPS(1);
11980 
11981  if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
11982  {
11983  if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
11984  {
11985  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
11986 
11987  if (item != null)
11988  {
11989  switch (mask)
11990  {
11991  case 0:
11992  item.BasePermissions = (uint)value;
11993  break;
11994  case 1:
11995  item.CurrentPermissions = (uint)value;
11996  break;
11997  case 2:
11998  item.GroupPermissions = (uint)value;
11999  break;
12000  case 3:
12001  item.EveryonePermissions = (uint)value;
12002  break;
12003  case 4:
12004  item.NextPermissions = (uint)value;
12005  break;
12006  }
12007  }
12008  }
12009  }
12010  }
12011 
12012  public LSL_String llGetInventoryCreator(string itemName)
12013  {
12014  m_host.AddScriptLPS(1);
12015 
12016  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
12017 
12018  if (item == null)
12019  {
12020  Error("llGetInventoryCreator", "Can't find item '" + item + "'");
12021 
12022  return String.Empty;
12023  }
12024 
12025  return item.CreatorID.ToString();
12026  }
12027 
12028  public void llOwnerSay(string msg)
12029  {
12030  m_host.AddScriptLPS(1);
12031 
12032  World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0,
12033  m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
12034 // IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
12035 // wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
12036  }
12037 
12039  {
12040  m_host.AddScriptLPS(1);
12041  if (m_UrlModule != null)
12042  return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID, null).ToString();
12043  return UUID.Zero.ToString();
12044  }
12045 
12046  public LSL_String llRequestSimulatorData(string simulator, int data)
12047  {
12048  IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL");
12049 
12050  try
12051  {
12052  m_host.AddScriptLPS(1);
12053 
12054  string reply = String.Empty;
12055 
12056  GridRegion info;
12057 
12058  if (World.RegionInfo.RegionName == simulator)
12059  info = new GridRegion(World.RegionInfo);
12060  else
12061  info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
12062 
12063  switch (data)
12064  {
12065  case ScriptBaseClass.DATA_SIM_POS:
12066  if (info == null)
12067  {
12068  ScriptSleep(m_sleepMsOnRequestSimulatorData);
12069  return UUID.Zero.ToString();
12070  }
12071 
12072  bool isHypergridRegion = false;
12073 
12074  if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "")
12075  {
12076  // Hypergrid is currently placing real destination region co-ords into RegionSecret.
12077  // But other code can also use this field for a genuine RegionSecret! Therefore, if
12078  // anything is present we need to disambiguate.
12079  //
12080  // FIXME: Hypergrid should be storing this data in a different field.
12081  RegionFlags regionFlags
12082  = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(
12083  info.ScopeID, info.RegionID);
12084  isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0;
12085  }
12086 
12087  if (isHypergridRegion)
12088  {
12089  uint rx = 0, ry = 0;
12090  Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry);
12091 
12092  reply = new LSL_Vector(
12093  rx,
12094  ry,
12095  0).ToString();
12096  }
12097  else
12098  {
12099  // Local grid co-oridnates
12100  reply = new LSL_Vector(
12101  info.RegionLocX,
12102  info.RegionLocY,
12103  0).ToString();
12104  }
12105  break;
12106  case ScriptBaseClass.DATA_SIM_STATUS:
12107  if (info != null)
12108  reply = "up"; // Duh!
12109  else
12110  reply = "unknown";
12111  break;
12112  case ScriptBaseClass.DATA_SIM_RATING:
12113  if (info == null)
12114  {
12115  ScriptSleep(m_sleepMsOnRequestSimulatorData);
12116  return UUID.Zero.ToString();
12117  }
12118  int access = info.Maturity;
12119  if (access == 0)
12120  reply = "PG";
12121  else if (access == 1)
12122  reply = "MATURE";
12123  else if (access == 2)
12124  reply = "ADULT";
12125  else
12126  reply = "UNKNOWN";
12127  break;
12128  case ScriptBaseClass.DATA_SIM_RELEASE:
12129  if (ossl != null)
12130  ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData");
12131  reply = "OpenSim";
12132  break;
12133  default:
12134  ScriptSleep(m_sleepMsOnRequestSimulatorData);
12135  return UUID.Zero.ToString(); // Raise no event
12136  }
12137  UUID rq = UUID.Random();
12138 
12139  UUID tid = AsyncCommands.
12140  DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
12141 
12142  AsyncCommands.
12143  DataserverPlugin.DataserverReply(rq.ToString(), reply);
12144 
12145  ScriptSleep(m_sleepMsOnRequestSimulatorData);
12146  return tid.ToString();
12147  }
12148  catch(Exception)
12149  {
12150  //m_log.Error("[LSL_API]: llRequestSimulatorData" + e.ToString());
12151  return UUID.Zero.ToString();
12152  }
12153  }
12154 
12156  {
12157  m_host.AddScriptLPS(1);
12158 
12159  if (m_UrlModule != null)
12160  return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID, null).ToString();
12161  return UUID.Zero.ToString();
12162  }
12163 
12164  public void llForceMouselook(int mouselook)
12165  {
12166  m_host.AddScriptLPS(1);
12167  m_host.SetForceMouselook(mouselook != 0);
12168  }
12169 
12170  public LSL_Float llGetObjectMass(string id)
12171  {
12172  m_host.AddScriptLPS(1);
12173  UUID key = new UUID();
12174  if (UUID.TryParse(id, out key))
12175  {
12176  // return total object mass
12177  SceneObjectPart part = World.GetSceneObjectPart(key);
12178  if (part != null)
12179  return part.ParentGroup.GetMass();
12180 
12181  // the object is null so the key is for an avatar
12182  ScenePresence avatar = World.GetScenePresence(key);
12183  if (avatar != null)
12184  {
12185  if (avatar.IsChildAgent)
12186  {
12187  // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
12188  // child agents have a mass of 1.0
12189  return 1;
12190  }
12191  else
12192  {
12193  return (double)avatar.GetMass();
12194  }
12195  }
12196  }
12197  return 0;
12198  }
12199 
12211 
12212  public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
12213  {
12214  LSL_List pref;
12215 
12216  m_host.AddScriptLPS(1);
12217 
12218  // Note that although we have normalized, both
12219  // indices could still be negative.
12220  if (start < 0)
12221  {
12222  start = start+dest.Length;
12223  }
12224 
12225  if (end < 0)
12226  {
12227  end = end+dest.Length;
12228  }
12229  // The comventional case, remove a sequence starting with
12230  // start and ending with end. And then insert the source
12231  // list.
12232  if (start <= end)
12233  {
12234  // If greater than zero, then there is going to be a
12235  // surviving prefix. Otherwise the inclusive nature
12236  // of the indices mean that we're going to add the
12237  // source list as a prefix.
12238  if (start > 0)
12239  {
12240  pref = dest.GetSublist(0,start-1);
12241  // Only add a suffix if there is something
12242  // beyond the end index (it's inclusive too).
12243  if (end + 1 < dest.Length)
12244  {
12245  return pref + src + dest.GetSublist(end + 1, -1);
12246  }
12247  else
12248  {
12249  return pref + src;
12250  }
12251  }
12252  // If start is less than or equal to zero, then
12253  // the new list is simply a prefix. We still need to
12254  // figure out any necessary surgery to the destination
12255  // based upon end. Note that if end exceeds the upper
12256  // bound in this case, the entire destination list
12257  // is removed.
12258  else if (start == 0)
12259  {
12260  if (end + 1 < dest.Length)
12261  return src + dest.GetSublist(end + 1, -1);
12262  else
12263  return src;
12264  }
12265  else // Start < 0
12266  {
12267  if (end + 1 < dest.Length)
12268  return dest.GetSublist(end + 1, -1);
12269  else
12270  return new LSL_List();
12271  }
12272  }
12273  // Finally, if start > end, we strip away a prefix and
12274  // a suffix, to leave the list that sits <between> ens
12275  // and start, and then tag on the src list. AT least
12276  // that's my interpretation. We can get sublist to do
12277  // this for us. Note that one, or both of the indices
12278  // might have been negative.
12279  else
12280  {
12281  return dest.GetSublist(end + 1, start - 1) + src;
12282  }
12283  }
12284 
12285  public void llLoadURL(string avatar_id, string message, string url)
12286  {
12287  m_host.AddScriptLPS(1);
12288 
12289  IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
12290  if (null != dm)
12291  dm.SendUrlToUser(
12292  new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url);
12293 
12294  ScriptSleep(m_sleepMsOnLoadURL);
12295  }
12296 
12297  public void llParcelMediaCommandList(LSL_List commandList)
12298  {
12299  // TODO: Not implemented yet (missing in libomv?):
12300  // PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
12301 
12302  m_host.AddScriptLPS(1);
12303 
12304  // according to the docs, this command only works if script owner and land owner are the same
12305  // lets add estate owners and gods, too, and use the generic permission check.
12306  ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12307  if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia, false)) return;
12308 
12309  bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
12310  byte loop = 0;
12311 
12312  LandData landData = landObject.LandData;
12313  string url = landData.MediaURL;
12314  string texture = landData.MediaID.ToString();
12315  bool autoAlign = landData.MediaAutoScale != 0;
12316  string mediaType = ""; // TODO these have to be added as soon as LandData supports it
12317  string description = "";
12318  int width = 0;
12319  int height = 0;
12320 
12321  ParcelMediaCommandEnum? commandToSend = null;
12322  float time = 0.0f; // default is from start
12323 
12324  ScenePresence presence = null;
12325 
12326  for (int i = 0; i < commandList.Data.Length; i++)
12327  {
12328  ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i];
12329  switch (command)
12330  {
12331  case ParcelMediaCommandEnum.Agent:
12332  // we send only to one agent
12333  if ((i + 1) < commandList.Length)
12334  {
12335  if (commandList.Data[i + 1] is LSL_String)
12336  {
12337  UUID agentID;
12338  if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID))
12339  {
12340  presence = World.GetScenePresence(agentID);
12341  }
12342  }
12343  else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
12344  ++i;
12345  }
12346  break;
12347 
12348  case ParcelMediaCommandEnum.Loop:
12349  loop = 1;
12350  commandToSend = command;
12351  update = true; //need to send the media update packet to set looping
12352  break;
12353 
12354  case ParcelMediaCommandEnum.Play:
12355  loop = 0;
12356  commandToSend = command;
12357  update = true; //need to send the media update packet to make sure it doesn't loop
12358  break;
12359 
12360  case ParcelMediaCommandEnum.Pause:
12361  case ParcelMediaCommandEnum.Stop:
12362  case ParcelMediaCommandEnum.Unload:
12363  commandToSend = command;
12364  break;
12365 
12366  case ParcelMediaCommandEnum.Url:
12367  if ((i + 1) < commandList.Length)
12368  {
12369  if (commandList.Data[i + 1] is LSL_String)
12370  {
12371  url = (LSL_String)commandList.Data[i + 1];
12372  update = true;
12373  }
12374  else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string");
12375  ++i;
12376  }
12377  break;
12378 
12379  case ParcelMediaCommandEnum.Texture:
12380  if ((i + 1) < commandList.Length)
12381  {
12382  if (commandList.Data[i + 1] is LSL_String)
12383  {
12384  texture = (LSL_String)commandList.Data[i + 1];
12385  update = true;
12386  }
12387  else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or a key");
12388  ++i;
12389  }
12390  break;
12391 
12392  case ParcelMediaCommandEnum.Time:
12393  if ((i + 1) < commandList.Length)
12394  {
12395  if (commandList.Data[i + 1] is LSL_Float)
12396  {
12397  time = (float)(LSL_Float)commandList.Data[i + 1];
12398  }
12399  else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float");
12400  ++i;
12401  }
12402  break;
12403 
12404  case ParcelMediaCommandEnum.AutoAlign:
12405  if ((i + 1) < commandList.Length)
12406  {
12407  if (commandList.Data[i + 1] is LSL_Integer)
12408  {
12409  autoAlign = (LSL_Integer)commandList.Data[i + 1];
12410  update = true;
12411  }
12412 
12413  else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer");
12414  ++i;
12415  }
12416  break;
12417 
12418  case ParcelMediaCommandEnum.Type:
12419  if ((i + 1) < commandList.Length)
12420  {
12421  if (commandList.Data[i + 1] is LSL_String)
12422  {
12423  mediaType = (LSL_String)commandList.Data[i + 1];
12424  update = true;
12425  }
12426  else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string");
12427  ++i;
12428  }
12429  break;
12430 
12431  case ParcelMediaCommandEnum.Desc:
12432  if ((i + 1) < commandList.Length)
12433  {
12434  if (commandList.Data[i + 1] is LSL_String)
12435  {
12436  description = (LSL_String)commandList.Data[i + 1];
12437  update = true;
12438  }
12439  else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string");
12440  ++i;
12441  }
12442  break;
12443 
12444  case ParcelMediaCommandEnum.Size:
12445  if ((i + 2) < commandList.Length)
12446  {
12447  if (commandList.Data[i + 1] is LSL_Integer)
12448  {
12449  if (commandList.Data[i + 2] is LSL_Integer)
12450  {
12451  width = (LSL_Integer)commandList.Data[i + 1];
12452  height = (LSL_Integer)commandList.Data[i + 2];
12453  update = true;
12454  }
12455  else Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer");
12456  }
12457  else Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer");
12458  i += 2;
12459  }
12460  break;
12461 
12462  default:
12463  NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString());
12464  break;
12465  }//end switch
12466  }//end for
12467 
12468  // if we didn't get a presence, we send to all and change the url
12469  // if we did get a presence, we only send to the agent specified, and *don't change the land settings*!
12470 
12471  // did something important change or do we only start/stop/pause?
12472  if (update)
12473  {
12474  if (presence == null)
12475  {
12476  // we send to all
12477  landData.MediaID = new UUID(texture);
12478  landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0;
12479  landData.MediaWidth = width;
12480  landData.MediaHeight = height;
12481  landData.MediaType = mediaType;
12482 
12483  // do that one last, it will cause a ParcelPropertiesUpdate
12484  landObject.SetMediaUrl(url);
12485 
12486  // now send to all (non-child) agents in the parcel
12487  World.ForEachRootScenePresence(delegate(ScenePresence sp)
12488  {
12489  if (sp.currentParcelUUID == landData.GlobalID)
12490  {
12491  sp.ControllingClient.SendParcelMediaUpdate(landData.MediaURL,
12492  landData.MediaID,
12493  landData.MediaAutoScale,
12494  mediaType,
12495  description,
12496  width, height,
12497  loop);
12498  }
12499  });
12500  }
12501  else if (!presence.IsChildAgent)
12502  {
12503  // we only send to one (root) agent
12504  presence.ControllingClient.SendParcelMediaUpdate(url,
12505  new UUID(texture),
12506  autoAlign ? (byte)1 : (byte)0,
12507  mediaType,
12508  description,
12509  width, height,
12510  loop);
12511  }
12512  }
12513 
12514  if (commandToSend != null)
12515  {
12516  // the commandList contained a start/stop/... command, too
12517  if (presence == null)
12518  {
12519  // send to all (non-child) agents in the parcel
12520  World.ForEachRootScenePresence(delegate(ScenePresence sp)
12521  {
12522  if (sp.currentParcelUUID == landData.GlobalID)
12523  {
12524  sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
12525  (ParcelMediaCommandEnum)commandToSend, time);
12526  }
12527  });
12528  }
12529  else if (!presence.IsChildAgent)
12530  {
12531  presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
12532  (ParcelMediaCommandEnum)commandToSend, time);
12533  }
12534  }
12535  ScriptSleep(m_sleepMsOnParcelMediaCommandList);
12536  }
12537 
12539  {
12540  m_host.AddScriptLPS(1);
12541  LSL_List list = new LSL_List();
12542  //TO DO: make the implementation for the missing commands
12543  //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
12544  for (int i = 0; i < aList.Data.Length; i++)
12545  {
12546 
12547  if (aList.Data[i] != null)
12548  {
12549  switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
12550  {
12551  case ParcelMediaCommandEnum.Url:
12552  list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
12553  break;
12554  case ParcelMediaCommandEnum.Desc:
12555  list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description));
12556  break;
12557  case ParcelMediaCommandEnum.Texture:
12558  list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString()));
12559  break;
12560  case ParcelMediaCommandEnum.Type:
12561  list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType));
12562  break;
12563  case ParcelMediaCommandEnum.Size:
12564  list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth));
12565  list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight));
12566  break;
12567  default:
12568  ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
12569  NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
12570  break;
12571  }
12572 
12573  }
12574  }
12575  ScriptSleep(m_sleepMsOnParcelMediaQuery);
12576  return list;
12577  }
12578 
12579  public LSL_Integer llModPow(int a, int b, int c)
12580  {
12581  m_host.AddScriptLPS(1);
12582  Int64 tmp = 0;
12583  Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
12584  ScriptSleep(m_sleepMsOnModPow);
12585  return Convert.ToInt32(tmp);
12586  }
12587 
12588  public LSL_Integer llGetInventoryType(string name)
12589  {
12590  m_host.AddScriptLPS(1);
12591 
12592  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
12593 
12594  if (item == null)
12595  return -1;
12596 
12597  return item.Type;
12598  }
12599 
12600  public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
12601  {
12602  m_host.AddScriptLPS(1);
12603 
12604  if (quick_pay_buttons.Data.Length < 4)
12605  {
12606  int x;
12607  for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
12608  {
12609  quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
12610  }
12611  }
12612  int[] nPrice = new int[5];
12613  nPrice[0] = price;
12614  nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
12615  nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
12616  nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
12617  nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
12618  m_host.ParentGroup.RootPart.PayPrice = nPrice;
12619  m_host.ParentGroup.HasGroupChanged = true;
12620  }
12621 
12623  {
12624  m_host.AddScriptLPS(1);
12625 
12626  if (m_item.PermsGranter == UUID.Zero)
12627  return Vector3.Zero;
12628 
12629  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
12630  {
12631  Error("llGetCameraPos", "No permissions to track the camera");
12632  return Vector3.Zero;
12633  }
12634 
12635 // ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
12636  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
12637  if (presence != null)
12638  {
12639  LSL_Vector pos = new LSL_Vector(presence.CameraPosition);
12640  return pos;
12641  }
12642 
12643  return Vector3.Zero;
12644  }
12645 
12647  {
12648  m_host.AddScriptLPS(1);
12649 
12650  if (m_item.PermsGranter == UUID.Zero)
12651  return Quaternion.Identity;
12652 
12653  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
12654  {
12655  Error("llGetCameraRot", "No permissions to track the camera");
12656  return Quaternion.Identity;
12657  }
12658 
12659 // ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
12660  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
12661  if (presence != null)
12662  {
12663  return new LSL_Rotation(presence.CameraRotation);
12664  }
12665 
12666  return Quaternion.Identity;
12667  }
12668 
12669  public void llSetPrimURL(string url)
12670  {
12671  m_host.AddScriptLPS(1);
12672  Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead");
12673  ScriptSleep(m_sleepMsOnSetPrimURL);
12674  }
12675 
12676  public void llRefreshPrimURL()
12677  {
12678  m_host.AddScriptLPS(1);
12679  Deprecated("llRefreshPrimURL");
12680  ScriptSleep(m_sleepMsOnRefreshPrimURL);
12681  }
12682 
12683  public LSL_String llEscapeURL(string url)
12684  {
12685  m_host.AddScriptLPS(1);
12686  try
12687  {
12688  return Uri.EscapeDataString(url);
12689  }
12690  catch (Exception ex)
12691  {
12692  return "llEscapeURL: " + ex.ToString();
12693  }
12694  }
12695 
12696  public LSL_String llUnescapeURL(string url)
12697  {
12698  m_host.AddScriptLPS(1);
12699  try
12700  {
12701  return Uri.UnescapeDataString(url);
12702  }
12703  catch (Exception ex)
12704  {
12705  return "llUnescapeURL: " + ex.ToString();
12706  }
12707  }
12708 
12709  public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt)
12710  {
12711  m_host.AddScriptLPS(1);
12712  DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
12713  if (detectedParams == null)
12714  {
12715  if (m_host.ParentGroup.IsAttachment == true)
12716  {
12717  detectedParams = new DetectParams();
12718  detectedParams.Key = m_host.OwnerID;
12719  }
12720  else
12721  {
12722  return;
12723  }
12724  }
12725 
12726  ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
12727  if (avatar != null)
12728  {
12729  avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
12730  simname, pos, lookAt);
12731  }
12732  ScriptSleep(m_sleepMsOnMapDestination);
12733  }
12734 
12735  public void llAddToLandBanList(string avatar, double hours)
12736  {
12737  m_host.AddScriptLPS(1);
12738  UUID key;
12739  ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12740  if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
12741  {
12742  int expires = 0;
12743  if (hours != 0)
12744  expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours);
12745 
12746  if (UUID.TryParse(avatar, out key))
12747  {
12748  int idx = land.LandData.ParcelAccessList.FindIndex(
12749  delegate(LandAccessEntry e)
12750  {
12751  if (e.AgentID == key && e.Flags == AccessList.Ban)
12752  return true;
12753  return false;
12754  });
12755 
12756  if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires)))
12757  return;
12758 
12759  if (idx != -1)
12760  land.LandData.ParcelAccessList.RemoveAt(idx);
12761 
12762  LandAccessEntry entry = new LandAccessEntry();
12763 
12764  entry.AgentID = key;
12765  entry.Flags = AccessList.Ban;
12766  entry.Expires = expires;
12767 
12768  land.LandData.ParcelAccessList.Add(entry);
12769 
12770  World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
12771  }
12772  }
12773  ScriptSleep(m_sleepMsOnAddToLandBanList);
12774  }
12775 
12776  public void llRemoveFromLandPassList(string avatar)
12777  {
12778  m_host.AddScriptLPS(1);
12779  UUID key;
12780  ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12781  if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed, false))
12782  {
12783  if (UUID.TryParse(avatar, out key))
12784  {
12785  int idx = land.LandData.ParcelAccessList.FindIndex(
12786  delegate(LandAccessEntry e)
12787  {
12788  if (e.AgentID == key && e.Flags == AccessList.Access)
12789  return true;
12790  return false;
12791  });
12792 
12793  if (idx != -1)
12794  {
12795  land.LandData.ParcelAccessList.RemoveAt(idx);
12796  World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
12797  }
12798  }
12799  }
12800  ScriptSleep(m_sleepMsOnRemoveFromLandPassList);
12801  }
12802 
12803  public void llRemoveFromLandBanList(string avatar)
12804  {
12805  m_host.AddScriptLPS(1);
12806  UUID key;
12807  ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12808  if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
12809  {
12810  if (UUID.TryParse(avatar, out key))
12811  {
12812  int idx = land.LandData.ParcelAccessList.FindIndex(
12813  delegate(LandAccessEntry e)
12814  {
12815  if (e.AgentID == key && e.Flags == AccessList.Ban)
12816  return true;
12817  return false;
12818  });
12819 
12820  if (idx != -1)
12821  {
12822  land.LandData.ParcelAccessList.RemoveAt(idx);
12823  World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
12824  }
12825  }
12826  }
12827  ScriptSleep(m_sleepMsOnRemoveFromLandBanList);
12828  }
12829 
12830  public void llSetCameraParams(LSL_List rules)
12831  {
12832  m_host.AddScriptLPS(1);
12833 
12834  // the object we are in
12835  UUID objectID = m_host.ParentUUID;
12836  if (objectID == UUID.Zero)
12837  return;
12838 
12839  // we need the permission first, to know which avatar we want to set the camera for
12840  UUID agentID = m_item.PermsGranter;
12841 
12842  if (agentID == UUID.Zero)
12843  return;
12844 
12845  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
12846  return;
12847 
12848  ScenePresence presence = World.GetScenePresence(agentID);
12849 
12850  // we are not interested in child-agents
12851  if (presence.IsChildAgent) return;
12852 
12853  SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
12854  object[] data = rules.Data;
12855  for (int i = 0; i < data.Length; ++i)
12856  {
12857  int type;
12858  try
12859  {
12860  type = Convert.ToInt32(data[i++].ToString());
12861  }
12862  catch
12863  {
12864  Error("llSetCameraParams", string.Format("Invalid camera param type {0}", data[i - 1]));
12865  return;
12866  }
12867  if (i >= data.Length) break; // odd number of entries => ignore the last
12868 
12869  // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
12870  switch (type)
12871  {
12872  case ScriptBaseClass.CAMERA_FOCUS:
12873  case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12874  case ScriptBaseClass.CAMERA_POSITION:
12875  LSL_Vector v = (LSL_Vector)data[i];
12876  try
12877  {
12878  parameters.Add(type + 1, (float)v.x);
12879  }
12880  catch
12881  {
12882  switch(type)
12883  {
12884  case ScriptBaseClass.CAMERA_FOCUS:
12885  Error("llSetCameraParams", "CAMERA_FOCUS: Parameter x is invalid");
12886  return;
12887  case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12888  Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter x is invalid");
12889  return;
12890  case ScriptBaseClass.CAMERA_POSITION:
12891  Error("llSetCameraParams", "CAMERA_POSITION: Parameter x is invalid");
12892  return;
12893  }
12894  }
12895  try
12896  {
12897  parameters.Add(type + 2, (float)v.y);
12898  }
12899  catch
12900  {
12901  switch(type)
12902  {
12903  case ScriptBaseClass.CAMERA_FOCUS:
12904  Error("llSetCameraParams", "CAMERA_FOCUS: Parameter y is invalid");
12905  return;
12906  case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12907  Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter y is invalid");
12908  return;
12909  case ScriptBaseClass.CAMERA_POSITION:
12910  Error("llSetCameraParams", "CAMERA_POSITION: Parameter y is invalid");
12911  return;
12912  }
12913  }
12914  try
12915  {
12916  parameters.Add(type + 3, (float)v.z);
12917  }
12918  catch
12919  {
12920  switch(type)
12921  {
12922  case ScriptBaseClass.CAMERA_FOCUS:
12923  Error("llSetCameraParams", "CAMERA_FOCUS: Parameter z is invalid");
12924  return;
12925  case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12926  Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter z is invalid");
12927  return;
12928  case ScriptBaseClass.CAMERA_POSITION:
12929  Error("llSetCameraParams", "CAMERA_POSITION: Parameter z is invalid");
12930  return;
12931  }
12932  }
12933  break;
12934  default:
12935  // TODO: clean that up as soon as the implicit casts are in
12936  if (data[i] is LSL_Float)
12937  parameters.Add(type, (float)((LSL_Float)data[i]).value);
12938  else if (data[i] is LSL_Integer)
12939  parameters.Add(type, (float)((LSL_Integer)data[i]).value);
12940  else
12941  {
12942  try
12943  {
12944  parameters.Add(type, Convert.ToSingle(data[i]));
12945  }
12946  catch
12947  {
12948  Error("llSetCameraParams", string.Format("{0}: Parameter is invalid", type));
12949  }
12950  }
12951  break;
12952  }
12953  }
12954  if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
12955  }
12956 
12957  public void llClearCameraParams()
12958  {
12959  m_host.AddScriptLPS(1);
12960 
12961  // the object we are in
12962  UUID objectID = m_host.ParentUUID;
12963  if (objectID == UUID.Zero)
12964  return;
12965 
12966  // we need the permission first, to know which avatar we want to clear the camera for
12967  UUID agentID = m_item.PermsGranter;
12968 
12969  if (agentID == UUID.Zero)
12970  return;
12971 
12972  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
12973  return;
12974 
12975  ScenePresence presence = World.GetScenePresence(agentID);
12976 
12977  // we are not interested in child-agents
12978  if (presence.IsChildAgent)
12979  return;
12980 
12981  presence.ControllingClient.SendClearFollowCamProperties(objectID);
12982  }
12983 
12984  public LSL_Float llListStatistics(int operation, LSL_List src)
12985  {
12986  m_host.AddScriptLPS(1);
12987  switch (operation)
12988  {
12989  case ScriptBaseClass.LIST_STAT_RANGE:
12990  return src.Range();
12991  case ScriptBaseClass.LIST_STAT_MIN:
12992  return src.Min();
12993  case ScriptBaseClass.LIST_STAT_MAX:
12994  return src.Max();
12995  case ScriptBaseClass.LIST_STAT_MEAN:
12996  return src.Mean();
12997  case ScriptBaseClass.LIST_STAT_MEDIAN:
12998  return LSL_List.ToDoubleList(src).Median();
12999  case ScriptBaseClass.LIST_STAT_NUM_COUNT:
13000  return src.NumericLength();
13001  case ScriptBaseClass.LIST_STAT_STD_DEV:
13002  return src.StdDev();
13003  case ScriptBaseClass.LIST_STAT_SUM:
13004  return src.Sum();
13005  case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
13006  return src.SumSqrs();
13007  case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
13008  return src.GeometricMean();
13009  case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
13010  return src.HarmonicMean();
13011  default:
13012  return 0.0;
13013  }
13014  }
13015 
13017  {
13018  m_host.AddScriptLPS(1);
13019  return Util.UnixTimeSinceEpoch();
13020  }
13021 
13023  {
13024  m_host.AddScriptLPS(1);
13025  return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).LandData.Flags;
13026  }
13027 
13029  {
13030  m_host.AddScriptLPS(1);
13031  IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
13032  if (estate == null)
13033  return 67108864;
13034  return (int)estate.GetRegionFlags();
13035  }
13036 
13037  public LSL_String llXorBase64StringsCorrect(string str1, string str2)
13038  {
13039  m_host.AddScriptLPS(1);
13040 
13041  if (str1 == String.Empty)
13042  return String.Empty;
13043  if (str2 == String.Empty)
13044  return str1;
13045 
13046  int len = str2.Length;
13047  if ((len % 4) != 0) // LL is EVIL!!!!
13048  {
13049  while (str2.EndsWith("="))
13050  str2 = str2.Substring(0, str2.Length - 1);
13051 
13052  len = str2.Length;
13053  int mod = len % 4;
13054 
13055  if (mod == 1)
13056  str2 = str2.Substring(0, str2.Length - 1);
13057  else if (mod == 2)
13058  str2 += "==";
13059  else if (mod == 3)
13060  str2 += "=";
13061  }
13062 
13063  byte[] data1;
13064  byte[] data2;
13065  try
13066  {
13067  data1 = Convert.FromBase64String(str1);
13068  data2 = Convert.FromBase64String(str2);
13069  }
13070  catch (Exception)
13071  {
13072  return new LSL_String(String.Empty);
13073  }
13074 
13075  byte[] d2 = new Byte[data1.Length];
13076  int pos = 0;
13077 
13078  if (data1.Length <= data2.Length)
13079  {
13080  Array.Copy(data2, 0, d2, 0, data1.Length);
13081  }
13082  else
13083  {
13084  while (pos < data1.Length)
13085  {
13086  len = data1.Length - pos;
13087  if (len > data2.Length)
13088  len = data2.Length;
13089 
13090  Array.Copy(data2, 0, d2, pos, len);
13091  pos += len;
13092  }
13093  }
13094 
13095  for (pos = 0 ; pos < data1.Length ; pos++ )
13096  data1[pos] ^= d2[pos];
13097 
13098  return Convert.ToBase64String(data1);
13099  }
13100 
13101  public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
13102  {
13103  // Partial implementation: support for parameter flags needed
13104  // see http://wiki.secondlife.com/wiki/LlHTTPRequest
13105  // parameter flags support are implemented in ScriptsHttpRequests.cs
13106  // in StartHttpRequest
13107 
13108  m_host.AddScriptLPS(1);
13109  IHttpRequestModule httpScriptMod =
13110  m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
13111  List<string> param = new List<string>();
13112  bool ok;
13113  Int32 flag;
13114 
13115  for (int i = 0; i < parameters.Data.Length; i += 2)
13116  {
13117  ok = Int32.TryParse(parameters.Data[i].ToString(), out flag);
13118  if (!ok || flag < 0 ||
13119  flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE)
13120  {
13121  Error("llHTTPRequest", "Parameter " + i.ToString() + " is an invalid flag");
13122  }
13123 
13124  param.Add(parameters.Data[i].ToString()); //Add parameter flag
13125 
13126  if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER)
13127  {
13128  param.Add(parameters.Data[i+1].ToString()); //Add parameter value
13129  }
13130  else
13131  {
13132  //Parameters are in pairs and custom header takes
13133  //arguments in pairs so adjust for header marker.
13134  ++i;
13135 
13136  //Maximum of 8 headers are allowed based on the
13137  //Second Life documentation for llHTTPRequest.
13138  for (int count = 1; count <= 8; ++count)
13139  {
13140  //Enough parameters remaining for (another) header?
13141  if (parameters.Data.Length - i < 2)
13142  {
13143  //There must be at least one name/value pair for custom header
13144  if (count == 1)
13145  Error("llHTTPRequest", "Missing name/value for custom header at parameter " + i.ToString());
13146  break;
13147  }
13148 
13149  if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase))
13150  Error("llHTTPRequest", "Name is invalid as a custom header at parameter " + i.ToString());
13151 
13152  param.Add(parameters.Data[i].ToString());
13153  param.Add(parameters.Data[i+1].ToString());
13154 
13155  //Have we reached the end of the list of headers?
13156  //End is marked by a string with a single digit.
13157  if (i+2 >= parameters.Data.Length ||
13158  Char.IsDigit(parameters.Data[i].ToString()[0]))
13159  {
13160  break;
13161  }
13162 
13163  i += 2;
13164  }
13165  }
13166  }
13167 
13168  Vector3 position = m_host.AbsolutePosition;
13169  Vector3 velocity = m_host.Velocity;
13170  Quaternion rotation = m_host.RotationOffset;
13171  string ownerName = String.Empty;
13172  ScenePresence scenePresence = World.GetScenePresence(m_host.OwnerID);
13173  if (scenePresence == null)
13174  ownerName = resolveName(m_host.OwnerID);
13175  else
13176  ownerName = scenePresence.Name;
13177 
13178  RegionInfo regionInfo = World.RegionInfo;
13179 
13180  Dictionary<string, string> httpHeaders = new Dictionary<string, string>();
13181 
13182  string shard = "OpenSim";
13183  IConfigSource config = m_ScriptEngine.ConfigSource;
13184  if (config.Configs["Network"] != null)
13185  {
13186  shard = config.Configs["Network"].GetString("shard", shard);
13187  }
13188 
13189  httpHeaders["X-SecondLife-Shard"] = shard;
13190  httpHeaders["X-SecondLife-Object-Name"] = m_host.Name;
13191  httpHeaders["X-SecondLife-Object-Key"] = m_host.UUID.ToString();
13192  httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY);
13193  httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z);
13194  httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z);
13195  httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W);
13196  httpHeaders["X-SecondLife-Owner-Name"] = ownerName;
13197  httpHeaders["X-SecondLife-Owner-Key"] = m_host.OwnerID.ToString();
13198  string userAgent = config.Configs["Network"].GetString("user_agent", null);
13199  if (userAgent != null)
13200  httpHeaders["User-Agent"] = userAgent;
13201 
13202  // See if the URL contains any header hacks
13203  string[] urlParts = url.Split(new char[] {'\n'});
13204  if (urlParts.Length > 1)
13205  {
13206  // Iterate the passed headers and parse them
13207  for (int i = 1 ; i < urlParts.Length ; i++ )
13208  {
13209  // The rest of those would be added to the body in SL.
13210  // Let's not do that.
13211  if (urlParts[i] == String.Empty)
13212  break;
13213 
13214  // See if this could be a valid header
13215  string[] headerParts = urlParts[i].Split(new char[] {':'}, 2);
13216  if (headerParts.Length != 2)
13217  continue;
13218 
13219  string headerName = headerParts[0].Trim();
13220  string headerValue = headerParts[1].Trim();
13221 
13222  // Filter out headers that could be used to abuse
13223  // another system or cloak the request
13224  if (headerName.ToLower() == "x-secondlife-shard" ||
13225  headerName.ToLower() == "x-secondlife-object-name" ||
13226  headerName.ToLower() == "x-secondlife-object-key" ||
13227  headerName.ToLower() == "x-secondlife-region" ||
13228  headerName.ToLower() == "x-secondlife-local-position" ||
13229  headerName.ToLower() == "x-secondlife-local-velocity" ||
13230  headerName.ToLower() == "x-secondlife-local-rotation" ||
13231  headerName.ToLower() == "x-secondlife-owner-name" ||
13232  headerName.ToLower() == "x-secondlife-owner-key" ||
13233  headerName.ToLower() == "connection" ||
13234  headerName.ToLower() == "content-length" ||
13235  headerName.ToLower() == "from" ||
13236  headerName.ToLower() == "host" ||
13237  headerName.ToLower() == "proxy-authorization" ||
13238  headerName.ToLower() == "referer" ||
13239  headerName.ToLower() == "trailer" ||
13240  headerName.ToLower() == "transfer-encoding" ||
13241  headerName.ToLower() == "via" ||
13242  headerName.ToLower() == "authorization")
13243  continue;
13244 
13245  httpHeaders[headerName] = headerValue;
13246  }
13247 
13248  // Finally, strip any protocol specifier from the URL
13249  url = urlParts[0].Trim();
13250  int idx = url.IndexOf(" HTTP/");
13251  if (idx != -1)
13252  url = url.Substring(0, idx);
13253  }
13254 
13255  string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
13256  Regex r = new Regex(authregex);
13257  int[] gnums = r.GetGroupNumbers();
13258  Match m = r.Match(url);
13259  if (m.Success)
13260  {
13261  for (int i = 1; i < gnums.Length; i++)
13262  {
13263  //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
13264  //CaptureCollection cc = g.Captures;
13265  }
13266  if (m.Groups.Count == 5)
13267  {
13268  httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
13269  url = m.Groups[1].ToString() + m.Groups[4].ToString();
13270  }
13271  }
13272 
13273  HttpInitialRequestStatus status;
13274  UUID reqID
13275  = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
13276 
13277  if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER)
13278  Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url));
13279 
13280  if (reqID != UUID.Zero)
13281  return reqID.ToString();
13282  else
13283  return null;
13284  }
13285 
13286 
13287  public void llHTTPResponse(LSL_Key id, int status, string body)
13288  {
13289  // Partial implementation: support for parameter flags needed
13290  // see http://wiki.secondlife.com/wiki/llHTTPResponse
13291 
13292  m_host.AddScriptLPS(1);
13293 
13294  if (m_UrlModule != null)
13295  m_UrlModule.HttpResponse(new UUID(id), status,body);
13296  }
13297 
13298  public void llResetLandBanList()
13299  {
13300  m_host.AddScriptLPS(1);
13301  LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData;
13302  if (land.OwnerID == m_host.OwnerID)
13303  {
13304  foreach (LandAccessEntry entry in land.ParcelAccessList)
13305  {
13306  if (entry.Flags == AccessList.Ban)
13307  {
13308  land.ParcelAccessList.Remove(entry);
13309  }
13310  }
13311  }
13312  ScriptSleep(m_sleepMsOnResetLandBanList);
13313  }
13314 
13315  public void llResetLandPassList()
13316  {
13317  m_host.AddScriptLPS(1);
13318  LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData;
13319  if (land.OwnerID == m_host.OwnerID)
13320  {
13321  foreach (LandAccessEntry entry in land.ParcelAccessList)
13322  {
13323  if (entry.Flags == AccessList.Access)
13324  {
13325  land.ParcelAccessList.Remove(entry);
13326  }
13327  }
13328  }
13329  ScriptSleep(m_sleepMsOnResetLandPassList);
13330  }
13331 
13332  public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
13333  {
13334  m_host.AddScriptLPS(1);
13335 
13336  ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
13337 
13338  if (lo == null)
13339  return 0;
13340 
13341  IPrimCounts pc = lo.PrimCounts;
13342 
13343  if (sim_wide != ScriptBaseClass.FALSE)
13344  {
13345  if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL)
13346  {
13347  return pc.Simulator;
13348  }
13349  else
13350  {
13351  // counts not implemented yet
13352  return 0;
13353  }
13354  }
13355  else
13356  {
13357  if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL)
13358  return pc.Total;
13359  else if (category == ScriptBaseClass.PARCEL_COUNT_OWNER)
13360  return pc.Owner;
13361  else if (category == ScriptBaseClass.PARCEL_COUNT_GROUP)
13362  return pc.Group;
13363  else if (category == ScriptBaseClass.PARCEL_COUNT_OTHER)
13364  return pc.Others;
13365  else if (category == ScriptBaseClass.PARCEL_COUNT_SELECTED)
13366  return pc.Selected;
13367  else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP)
13368  return 0; // counts not implemented yet
13369  }
13370 
13371  return 0;
13372  }
13373 
13375  {
13376  m_host.AddScriptLPS(1);
13377  LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
13378  LSL_List ret = new LSL_List();
13379  if (land != null)
13380  {
13381  foreach (KeyValuePair<UUID, int> detectedParams in land.GetLandObjectOwners())
13382  {
13383  ret.Add(new LSL_String(detectedParams.Key.ToString()));
13384  ret.Add(new LSL_Integer(detectedParams.Value));
13385  }
13386  }
13387  ScriptSleep(m_sleepMsOnGetParcelPrimOwners);
13388  return ret;
13389  }
13390 
13391  public LSL_Integer llGetObjectPrimCount(string object_id)
13392  {
13393  m_host.AddScriptLPS(1);
13394  SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id));
13395  if (part == null)
13396  {
13397  return 0;
13398  }
13399  else
13400  {
13401  return part.ParentGroup.PrimCount;
13402  }
13403  }
13404 
13405  public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide)
13406  {
13407  m_host.AddScriptLPS(1);
13408 
13409  ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
13410 
13411  if (lo == null)
13412  return 0;
13413 
13414  if (sim_wide != 0)
13415  return lo.GetSimulatorMaxPrimCount();
13416  else
13417  return lo.GetParcelMaxPrimCount();
13418  }
13419 
13421  {
13422  m_host.AddScriptLPS(1);
13423  LandData land = World.GetLandData(pos);
13424  if (land == null)
13425  {
13426  return new LSL_List(0);
13427  }
13428  LSL_List ret = new LSL_List();
13429  foreach (object o in param.Data)
13430  {
13431  switch (o.ToString())
13432  {
13433  case "0":
13434  ret.Add(new LSL_String(land.Name));
13435  break;
13436  case "1":
13437  ret.Add(new LSL_String(land.Description));
13438  break;
13439  case "2":
13440  ret.Add(new LSL_Key(land.OwnerID.ToString()));
13441  break;
13442  case "3":
13443  ret.Add(new LSL_Key(land.GroupID.ToString()));
13444  break;
13445  case "4":
13446  ret.Add(new LSL_Integer(land.Area));
13447  break;
13448  case "5":
13449  ret.Add(new LSL_Key(land.GlobalID.ToString()));
13450  break;
13451  default:
13452  ret.Add(new LSL_Integer(0));
13453  break;
13454  }
13455  }
13456  return ret;
13457  }
13458 
13459  public LSL_String llStringTrim(string src, int type)
13460  {
13461  m_host.AddScriptLPS(1);
13462  if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
13463  if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
13464  if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); }
13465  return src;
13466  }
13467 
13468  public LSL_List llGetObjectDetails(string id, LSL_List args)
13469  {
13470  m_host.AddScriptLPS(1);
13471 
13472  LSL_List ret = new LSL_List();
13473  UUID key = new UUID();
13474 
13475 
13476  if (UUID.TryParse(id, out key))
13477  {
13478  ScenePresence av = World.GetScenePresence(key);
13479 
13480  if (av != null)
13481  {
13482  foreach (object o in args.Data)
13483  {
13484  switch (int.Parse(o.ToString()))
13485  {
13486  case ScriptBaseClass.OBJECT_NAME:
13487  ret.Add(new LSL_String(av.Firstname + " " + av.Lastname));
13488  break;
13489  case ScriptBaseClass.OBJECT_DESC:
13490  ret.Add(new LSL_String(""));
13491  break;
13492  case ScriptBaseClass.OBJECT_POS:
13493  Vector3 avpos;
13494 
13495  if (av.ParentID != 0 && av.ParentPart != null &&
13496  av.ParentPart.ParentGroup != null && av.ParentPart.ParentGroup.RootPart != null )
13497  {
13498  avpos = av.OffsetPosition;
13499 
13500  if(!av.LegacySitOffsets)
13501  {
13502  Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
13503  avpos -= sitOffset;
13504  }
13505 
13506  SceneObjectPart sitRoot = av.ParentPart.ParentGroup.RootPart;
13507  avpos = sitRoot.GetWorldPosition() + avpos * sitRoot.GetWorldRotation();
13508  }
13509  else
13510  avpos = av.AbsolutePosition;
13511 
13512  ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
13513  break;
13514  case ScriptBaseClass.OBJECT_ROT:
13515  Quaternion avrot = av.GetWorldRotation();
13516  ret.Add(new LSL_Rotation(avrot));
13517  break;
13518  case ScriptBaseClass.OBJECT_VELOCITY:
13519  Vector3 avvel = av.GetWorldVelocity();
13520  ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
13521  break;
13522  case ScriptBaseClass.OBJECT_OWNER:
13523  ret.Add(new LSL_String(id));
13524  break;
13525  case ScriptBaseClass.OBJECT_GROUP:
13526  ret.Add(new LSL_String(UUID.Zero.ToString()));
13527  break;
13528  case ScriptBaseClass.OBJECT_CREATOR:
13529  ret.Add(new LSL_String(UUID.Zero.ToString()));
13530  break;
13531  // For the following 8 see the Object version below
13532  case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
13533  ret.Add(new LSL_Integer(av.RunningScriptCount()));
13534  break;
13535  case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
13536  ret.Add(new LSL_Integer(av.ScriptCount()));
13537  break;
13538  case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
13539  ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384));
13540  break;
13541  case ScriptBaseClass.OBJECT_SCRIPT_TIME:
13542  ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f));
13543  break;
13544  case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
13545  ret.Add(new LSL_Integer(1));
13546  break;
13547  case ScriptBaseClass.OBJECT_SERVER_COST:
13548  ret.Add(new LSL_Float(0));
13549  break;
13550  case ScriptBaseClass.OBJECT_STREAMING_COST:
13551  ret.Add(new LSL_Float(0));
13552  break;
13553  case ScriptBaseClass.OBJECT_PHYSICS_COST:
13554  ret.Add(new LSL_Float(0));
13555  break;
13556  case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
13557  ret.Add(new LSL_Float(0));
13558  break;
13559  case ScriptBaseClass.OBJECT_ROOT:
13560  SceneObjectPart p = av.ParentPart;
13561  if (p != null)
13562  {
13563  ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString()));
13564  }
13565  else
13566  {
13567  ret.Add(new LSL_String(id));
13568  }
13569  break;
13570  case ScriptBaseClass.OBJECT_ATTACHED_POINT:
13571  ret.Add(new LSL_Integer(0));
13572  break;
13573  case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding
13574  ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR));
13575  break;
13576  case ScriptBaseClass.OBJECT_PHYSICS:
13577  ret.Add(new LSL_Integer(0));
13578  break;
13579  case ScriptBaseClass.OBJECT_PHANTOM:
13580  ret.Add(new LSL_Integer(0));
13581  break;
13582  case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
13583  ret.Add(new LSL_Integer(0));
13584  break;
13585  case ScriptBaseClass.OBJECT_RENDER_WEIGHT:
13586  ret.Add(new LSL_Integer(-1));
13587  break;
13588  case ScriptBaseClass.OBJECT_HOVER_HEIGHT:
13589  ret.Add(new LSL_Float(0));
13590  break;
13591  case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE:
13592  LSL_Float shapeType;
13593  if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0)
13594  shapeType = new LSL_Float(1);
13595  else
13596  shapeType = new LSL_Float(0);
13597  ret.Add(shapeType);
13598  break;
13599  case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13600  ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY));
13601  break;
13602  default:
13603  // Invalid or unhandled constant.
13605  break;
13606  }
13607  }
13608 
13609  return ret;
13610  }
13611 
13612  SceneObjectPart obj = World.GetSceneObjectPart(key);
13613  if (obj != null)
13614  {
13615  foreach (object o in args.Data)
13616  {
13617  switch (int.Parse(o.ToString()))
13618  {
13619  case ScriptBaseClass.OBJECT_NAME:
13620  ret.Add(new LSL_String(obj.Name));
13621  break;
13622  case ScriptBaseClass.OBJECT_DESC:
13623  ret.Add(new LSL_String(obj.Description));
13624  break;
13625  case ScriptBaseClass.OBJECT_POS:
13626  Vector3 opos = obj.AbsolutePosition;
13627  ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
13628  break;
13629  case ScriptBaseClass.OBJECT_ROT:
13630  Quaternion rot = Quaternion.Identity;
13631 
13632  if (obj.ParentGroup.IsAttachment)
13633  {
13634  ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar);
13635 
13636  if (sp != null)
13637  rot = sp.GetWorldRotation();
13638  }
13639  else
13640  {
13641  if (obj.ParentGroup.RootPart == obj)
13642  rot = obj.ParentGroup.GroupRotation;
13643  else
13644  rot = obj.GetWorldRotation();
13645  }
13646 
13647  LSL_Rotation objrot = new LSL_Rotation(rot);
13648  ret.Add(objrot);
13649 
13650  break;
13651  case ScriptBaseClass.OBJECT_VELOCITY:
13652  Vector3 vel = Vector3.Zero;
13653 
13654  if (obj.ParentGroup.IsAttachment)
13655  {
13656  ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar);
13657 
13658  if (sp != null)
13659  vel = sp.GetWorldVelocity();
13660  }
13661  else
13662  {
13663  vel = obj.Velocity;
13664  }
13665 
13666  ret.Add(vel);
13667  break;
13668  case ScriptBaseClass.OBJECT_OWNER:
13669  ret.Add(new LSL_String(obj.OwnerID.ToString()));
13670  break;
13671  case ScriptBaseClass.OBJECT_GROUP:
13672  ret.Add(new LSL_String(obj.GroupID.ToString()));
13673  break;
13674  case ScriptBaseClass.OBJECT_CREATOR:
13675  ret.Add(new LSL_String(obj.CreatorID.ToString()));
13676  break;
13677  case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
13678  ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount()));
13679  break;
13680  case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
13681  ret.Add(new LSL_Integer(obj.ParentGroup.ScriptCount()));
13682  break;
13683  case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
13684  // The value returned in SL for mono scripts is 65536 * number of active scripts
13685  // and 16384 * number of active scripts for LSO. since llGetFreememory
13686  // is coded to give the LSO value use it here
13687  ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384));
13688  break;
13689  case ScriptBaseClass.OBJECT_SCRIPT_TIME:
13690  // Average cpu time in seconds per simulator frame expended on all scripts in the object
13691  ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f));
13692  break;
13693  case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
13694  // according to the SL wiki A prim or linkset will have prim
13695  // equivalent of the number of prims in a linkset if it does not
13696  // contain a mesh anywhere in the link set or is not a normal prim
13697  // The value returned in SL for normal prims is prim count
13698  ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
13699  break;
13700 
13701  // costs below may need to be diferent for root parts, need to check
13702  case ScriptBaseClass.OBJECT_SERVER_COST:
13703  // The linden calculation is here
13704  // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
13705  // The value returned in SL for normal prims looks like the prim count
13706  ret.Add(new LSL_Float(0));
13707  break;
13708  case ScriptBaseClass.OBJECT_STREAMING_COST:
13709  // The value returned in SL for normal prims is prim count * 0.06
13710  ret.Add(new LSL_Float(obj.StreamingCost));
13711  break;
13712  case ScriptBaseClass.OBJECT_PHYSICS_COST:
13713  // The value returned in SL for normal prims is prim count
13714  ret.Add(new LSL_Float(obj.PhysicsCost));
13715  break;
13716  case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
13717  ret.Add(new LSL_Float(0));
13718  break;
13719  case ScriptBaseClass.OBJECT_ROOT:
13720  ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString()));
13721  break;
13722  case ScriptBaseClass.OBJECT_ATTACHED_POINT:
13723  ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint));
13724  break;
13725  case ScriptBaseClass.OBJECT_PATHFINDING_TYPE:
13726  byte pcode = obj.Shape.PCode;
13727  if (obj.ParentGroup.AttachmentPoint != 0
13728  || pcode == (byte)PCode.Grass
13729  || pcode == (byte)PCode.Tree
13730  || pcode == (byte)PCode.NewTree)
13731  {
13732  ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER));
13733  }
13734  else
13735  {
13737  }
13738  break;
13739  case ScriptBaseClass.OBJECT_PHYSICS:
13740  if (obj.ParentGroup.AttachmentPoint != 0)
13741  {
13742  ret.Add(new LSL_Integer(0)); // Always false if attached
13743  }
13744  else
13745  {
13746  ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0));
13747  }
13748  break;
13749  case ScriptBaseClass.OBJECT_PHANTOM:
13750  if (obj.ParentGroup.AttachmentPoint != 0)
13751  {
13752  ret.Add(new LSL_Integer(0)); // Always false if attached
13753  }
13754  else
13755  {
13756  ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0));
13757  }
13758  break;
13759  case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
13760  ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0));
13761  break;
13762  case ScriptBaseClass.OBJECT_RENDER_WEIGHT:
13763  ret.Add(new LSL_Integer(0));
13764  break;
13765  case ScriptBaseClass.OBJECT_HOVER_HEIGHT:
13766  ret.Add(new LSL_Float(0));
13767  break;
13768  case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE:
13769  ret.Add(new LSL_Float(-1));
13770  break;
13771  case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13772  ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString()));
13773  break;
13774  default:
13775  // Invalid or unhandled constant.
13777  break;
13778  }
13779  }
13780 
13781  return ret;
13782  }
13783  }
13784 
13785  return new LSL_List();
13786  }
13787 
13788  internal UUID GetScriptByName(string name)
13789  {
13790  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
13791 
13792  if (item == null || item.Type != 10)
13793  return UUID.Zero;
13794 
13795  return item.ItemID;
13796  }
13797 
13803  internal void Error(string command, string message)
13804  {
13805  string text = command + ": " + message;
13806  if (text.Length > 1023)
13807  {
13808  text = text.Substring(0, 1023);
13809  }
13810 
13811  World.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, ScriptBaseClass.DEBUG_CHANNEL,
13812  m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
13813 
13814  IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
13815  if (wComm != null)
13816  {
13817  wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, text);
13818  }
13819  }
13820 
13826  internal void NotImplemented(string command, string message = "")
13827  {
13828  if (throwErrorOnNotImplemented)
13829  {
13830  if (message != "")
13831  {
13832  message = " - " + message;
13833  }
13834 
13835  throw new NotImplementedException("Command not implemented: " + command + message);
13836  }
13837  else
13838  {
13839  string text = "Command not implemented";
13840  if (message != "")
13841  {
13842  text = text + " - " + message;
13843  }
13844 
13845  Error(command, text);
13846  }
13847  }
13848 
13854  internal void Deprecated(string command, string message = "")
13855  {
13856  string text = "Command deprecated";
13857  if (message != "")
13858  {
13859  text = text + " - " + message;
13860  }
13861 
13862  Error(command, text);
13863  }
13864 
13865  public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
13866  protected void WithNotecard(UUID assetID, AssetRequestCallback cb)
13867  {
13868  World.AssetService.Get(assetID.ToString(), this,
13869  delegate(string i, object sender, AssetBase a)
13870  {
13871  UUID uuid = UUID.Zero;
13872  UUID.TryParse(i, out uuid);
13873  cb(uuid, a);
13874  });
13875  }
13876 
13878  {
13879  m_host.AddScriptLPS(1);
13880 
13881  UUID assetID = UUID.Zero;
13882 
13883  if (!UUID.TryParse(name, out assetID))
13884  {
13885  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
13886 
13887  if (item != null && item.Type == 7)
13888  assetID = item.AssetID;
13889  }
13890 
13891  if (assetID == UUID.Zero)
13892  {
13893  // => complain loudly, as specified by the LSL docs
13894  Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'");
13895 
13896  return UUID.Zero.ToString();
13897  }
13898 
13899  string reqIdentifier = UUID.Random().ToString();
13900 
13901  // was: UUID tid = tid = AsyncCommands.
13902  UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier);
13903 
13904  if (NotecardCache.IsCached(assetID))
13905  {
13906  AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString());
13907 
13908  ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines);
13909  return tid.ToString();
13910  }
13911 
13912  WithNotecard(assetID, delegate (UUID id, AssetBase a)
13913  {
13914  if (a == null || a.Type != 7)
13915  {
13916  Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'");
13917  return;
13918  }
13919 
13920  NotecardCache.Cache(id, a.Data);
13921  AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString());
13922  });
13923 
13924  ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines);
13925  return tid.ToString();
13926  }
13927 
13928  public LSL_String llGetNotecardLine(string name, int line)
13929  {
13930  m_host.AddScriptLPS(1);
13931 
13932  UUID assetID = UUID.Zero;
13933 
13934  if (!UUID.TryParse(name, out assetID))
13935  {
13936  TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
13937 
13938  if (item != null && item.Type == 7)
13939  assetID = item.AssetID;
13940  }
13941 
13942  if (assetID == UUID.Zero)
13943  {
13944  // => complain loudly, as specified by the LSL docs
13945  Error("llGetNotecardLine", "Can't find notecard '" + name + "'");
13946 
13947  return UUID.Zero.ToString();
13948  }
13949 
13950  string reqIdentifier = UUID.Random().ToString();
13951 
13952  // was: UUID tid = tid = AsyncCommands.
13953  UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier);
13954 
13955  if (NotecardCache.IsCached(assetID))
13956  {
13957  AsyncCommands.DataserverPlugin.DataserverReply(
13958  reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
13959 
13960  ScriptSleep(m_sleepMsOnGetNotecardLine);
13961  return tid.ToString();
13962  }
13963 
13964  WithNotecard(assetID, delegate (UUID id, AssetBase a)
13965  {
13966  if (a == null || a.Type != 7)
13967  {
13968  Error("llGetNotecardLine", "Can't find notecard '" + name + "'");
13969  return;
13970  }
13971 
13972  string data = Encoding.UTF8.GetString(a.Data);
13973  //m_log.Debug(data);
13974  NotecardCache.Cache(id, a.Data);
13975  AsyncCommands.DataserverPlugin.DataserverReply(
13976  reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
13977  });
13978 
13979  ScriptSleep(m_sleepMsOnGetNotecardLine);
13980  return tid.ToString();
13981  }
13982 
13983  public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
13984  {
13985  SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
13986  if (obj == null)
13987  return;
13988 
13989  if (obj.OwnerID != m_host.OwnerID)
13990  return;
13991 
13992  SetEntityParams(new List<ISceneEntity>() { obj }, rules, originFunc);
13993  }
13994 
13996  {
13997  SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
13998 
13999  LSL_List result = new LSL_List();
14000 
14001  if (obj != null && obj.OwnerID == m_host.OwnerID)
14002  {
14003  LSL_List remaining = GetPrimParams(obj, rules, ref result);
14004 
14005  while (remaining.Length > 2)
14006  {
14007  int linknumber = remaining.GetLSLIntegerItem(0);
14008  rules = remaining.GetSublist(1, -1);
14009  List<SceneObjectPart> parts = GetLinkParts(linknumber);
14010 
14011  foreach (SceneObjectPart part in parts)
14012  remaining = GetPrimParams(part, rules, ref result);
14013  }
14014  }
14015 
14016  return result;
14017  }
14018 
14019  public void print(string str)
14020  {
14021  // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print
14022  IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL");
14023  if (ossl != null)
14024  {
14025  ossl.CheckThreatLevel(ThreatLevel.High, "print");
14026  m_log.Info("LSL print():" + str);
14027  }
14028  }
14029 
14031  {
14032  List<SceneObjectPart> parts = GetLinkParts(link);
14033  if (parts.Count < 1)
14034  return 0;
14035 
14036  return GetNumberOfSides(parts[0]);
14037  }
14038 
14039  private string Name2Username(string name)
14040  {
14041  string[] parts = name.Split(new char[] {' '});
14042  if (parts.Length < 2)
14043  return name.ToLower();
14044  if (parts[1] == "Resident")
14045  return parts[0].ToLower();
14046 
14047  return name.Replace(" ", ".").ToLower();
14048  }
14049 
14050  public LSL_String llGetUsername(string id)
14051  {
14052  return Name2Username(llKey2Name(id));
14053  }
14054 
14055  public LSL_String llRequestUsername(string id)
14056  {
14057  UUID rq = UUID.Random();
14058 
14059  AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
14060 
14061  AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
14062 
14063  return rq.ToString();
14064  }
14065 
14066  public LSL_String llGetDisplayName(string id)
14067  {
14068  return llKey2Name(id);
14069  }
14070 
14072  {
14073  UUID rq = UUID.Random();
14074 
14075  AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
14076 
14077  AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
14078 
14079  return rq.ToString();
14080  }
14081 /*
14082  private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
14083  {
14084  m_SayShoutCount = 0;
14085  }
14086 */
14087  private struct Tri
14088  {
14089  public Vector3 p1;
14090  public Vector3 p2;
14091  public Vector3 p3;
14092  }
14093 
14094  private bool InBoundingBox(ScenePresence avatar, Vector3 point)
14095  {
14096  float height = avatar.Appearance.AvatarHeight;
14097  Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
14098  Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
14099 
14100  if (point.X > b1.X && point.X < b2.X &&
14101  point.Y > b1.Y && point.Y < b2.Y &&
14102  point.Z > b1.Z && point.Z < b2.Z)
14103  return true;
14104  return false;
14105  }
14106 
14107  private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
14108  {
14109  List<ContactResult> contacts = new List<ContactResult>();
14110 
14111  Vector3 ab = rayEnd - rayStart;
14112 
14113  World.ForEachScenePresence(delegate(ScenePresence sp)
14114  {
14115  Vector3 ac = sp.AbsolutePosition - rayStart;
14116 // Vector3 bc = sp.AbsolutePosition - rayEnd;
14117 
14118  double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
14119 
14120  if (d > 1.5)
14121  return;
14122 
14123  double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
14124 
14125  if (d2 > 0)
14126  return;
14127 
14128  double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
14129  Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
14130 
14131  if (!InBoundingBox(sp, p))
14132  return;
14133 
14134  ContactResult result = new ContactResult ();
14135  result.ConsumerID = sp.LocalId;
14136  result.Depth = Vector3.Distance(rayStart, p);
14137  result.Normal = Vector3.Zero;
14138  result.Pos = p;
14139 
14140  contacts.Add(result);
14141  });
14142 
14143  return contacts.ToArray();
14144  }
14145 
14146  private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
14147  {
14148  Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
14149  List<ContactResult> contacts = new List<ContactResult>();
14150 
14151  Vector3 ab = rayEnd - rayStart;
14152 
14153  World.ForEachSOG(delegate(SceneObjectGroup group)
14154  {
14155  if (m_host.ParentGroup == group)
14156  return;
14157 
14158  if (group.IsAttachment)
14159  return;
14160 
14161  if (group.RootPart.PhysActor == null)
14162  {
14163  if (!includePhantom)
14164  return;
14165  }
14166  else
14167  {
14168  if (group.RootPart.PhysActor.IsPhysical)
14169  {
14170  if (!includePhysical)
14171  return;
14172  }
14173  else
14174  {
14175  if (!includeNonPhysical)
14176  return;
14177  }
14178  }
14179 
14180  // Find the radius ouside of which we don't even need to hit test
14181  float minX;
14182  float maxX;
14183  float minY;
14184  float maxY;
14185  float minZ;
14186  float maxZ;
14187 
14188  float radius = 0.0f;
14189 
14190  group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
14191 
14192  if (Math.Abs(minX) > radius)
14193  radius = Math.Abs(minX);
14194  if (Math.Abs(minY) > radius)
14195  radius = Math.Abs(minY);
14196  if (Math.Abs(minZ) > radius)
14197  radius = Math.Abs(minZ);
14198  if (Math.Abs(maxX) > radius)
14199  radius = Math.Abs(maxX);
14200  if (Math.Abs(maxY) > radius)
14201  radius = Math.Abs(maxY);
14202  if (Math.Abs(maxZ) > radius)
14203  radius = Math.Abs(maxZ);
14204  radius = radius*1.413f;
14205  Vector3 ac = group.AbsolutePosition - rayStart;
14206 // Vector3 bc = group.AbsolutePosition - rayEnd;
14207 
14208  double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
14209 
14210  // Too far off ray, don't bother
14211  if (d > radius)
14212  return;
14213 
14214  // Behind ray, drop
14215  double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
14216  if (d2 > 0)
14217  return;
14218 
14219  ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
14220  EntityIntersection intersection = group.TestIntersection(ray, true, false);
14221  // Miss.
14222  if (!intersection.HitTF)
14223  return;
14224 
14225  Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ);
14226  Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ);
14227  //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z);
14228  if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X &&
14229  intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y &&
14230  intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z))
14231  return;
14232 
14233  ContactResult result = new ContactResult ();
14234  result.ConsumerID = group.LocalId;
14235 // result.Depth = intersection.distance;
14236  result.Normal = intersection.normal;
14237  result.Pos = intersection.ipoint;
14238  result.Depth = Vector3.Mag(rayStart - result.Pos);
14239 
14240  contacts.Add(result);
14241  });
14242 
14243  return contacts.ToArray();
14244  }
14245 
14246  private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
14247  {
14248  double[,] heightfield = World.Heightmap.GetDoubles();
14249  List<ContactResult> contacts = new List<ContactResult>();
14250 
14251  double min = 2048.0;
14252  double max = 0.0;
14253 
14254  // Find the min and max of the heightfield
14255  for (int x = 0 ; x < World.Heightmap.Width ; x++)
14256  {
14257  for (int y = 0 ; y < World.Heightmap.Height ; y++)
14258  {
14259  if (heightfield[x, y] > max)
14260  max = heightfield[x, y];
14261  if (heightfield[x, y] < min)
14262  min = heightfield[x, y];
14263  }
14264  }
14265 
14266 
14267  // A ray extends past rayEnd, but doesn't go back before
14268  // rayStart. If the start is above the highest point of the ground
14269  // and the ray goes up, we can't hit the ground. Ever.
14270  if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
14271  return null;
14272 
14273  // Same for going down
14274  if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
14275  return null;
14276 
14277  List<Tri> trilist = new List<Tri>();
14278 
14279  // Create our triangle list
14280  for (int x = 1 ; x < World.Heightmap.Width ; x++)
14281  {
14282  for (int y = 1 ; y < World.Heightmap.Height ; y++)
14283  {
14284  Tri t1 = new Tri();
14285  Tri t2 = new Tri();
14286 
14287  Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
14288  Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
14289  Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
14290  Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
14291 
14292  t1.p1 = p1;
14293  t1.p2 = p2;
14294  t1.p3 = p3;
14295 
14296  t2.p1 = p3;
14297  t2.p2 = p4;
14298  t2.p3 = p1;
14299 
14300  trilist.Add(t1);
14301  trilist.Add(t2);
14302  }
14303  }
14304 
14305  // Ray direction
14306  Vector3 rayDirection = rayEnd - rayStart;
14307 
14308  foreach (Tri t in trilist)
14309  {
14310  // Compute triangle plane normal and edges
14311  Vector3 u = t.p2 - t.p1;
14312  Vector3 v = t.p3 - t.p1;
14313  Vector3 n = Vector3.Cross(u, v);
14314 
14315  if (n == Vector3.Zero)
14316  continue;
14317 
14318  Vector3 w0 = rayStart - t.p1;
14319  double a = -Vector3.Dot(n, w0);
14320  double b = Vector3.Dot(n, rayDirection);
14321 
14322  // Not intersecting the plane, or in plane (same thing)
14323  // Ignoring this MAY cause the ground to not be detected
14324  // sometimes
14325  if (Math.Abs(b) < 0.000001)
14326  continue;
14327 
14328  double r = a / b;
14329 
14330  // ray points away from plane
14331  if (r < 0.0)
14332  continue;
14333 
14334  Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
14335 
14336  float uu = Vector3.Dot(u, u);
14337  float uv = Vector3.Dot(u, v);
14338  float vv = Vector3.Dot(v, v);
14339  Vector3 w = ip - t.p1;
14340  float wu = Vector3.Dot(w, u);
14341  float wv = Vector3.Dot(w, v);
14342  float d = uv * uv - uu * vv;
14343 
14344  float cs = (uv * wv - vv * wu) / d;
14345  if (cs < 0 || cs > 1.0)
14346  continue;
14347  float ct = (uv * wu - uu * wv) / d;
14348  if (ct < 0 || (cs + ct) > 1.0)
14349  continue;
14350 
14351  // Add contact point
14352  ContactResult result = new ContactResult ();
14353  result.ConsumerID = 0;
14354  result.Depth = Vector3.Distance(rayStart, ip);
14355  result.Normal = n;
14356  result.Pos = ip;
14357 
14358  contacts.Add(result);
14359  }
14360 
14361  if (contacts.Count == 0)
14362  return null;
14363 
14364  contacts.Sort(delegate(ContactResult a, ContactResult b)
14365  {
14366  return (int)(a.Depth - b.Depth);
14367  });
14368 
14369  return contacts[0];
14370  }
14371 /*
14372  // not done:
14373  private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
14374  {
14375  ContactResult[] contacts = null;
14376  World.ForEachSOG(delegate(SceneObjectGroup group)
14377  {
14378  if (m_host.ParentGroup == group)
14379  return;
14380 
14381  if (group.IsAttachment)
14382  return;
14383 
14384  if(group.RootPart.PhysActor != null)
14385  return;
14386 
14387  contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
14388  });
14389  return contacts;
14390  }
14391 */
14392 
14394  {
14395  // Use llCastRay V3 if configured
14396  if (m_useCastRayV3)
14397  return llCastRayV3(start, end, options);
14398 
14399  LSL_List list = new LSL_List();
14400 
14401  m_host.AddScriptLPS(1);
14402 
14403  Vector3 rayStart = start;
14404  Vector3 rayEnd = end;
14405  Vector3 dir = rayEnd - rayStart;
14406 
14407  float dist = Vector3.Mag(dir);
14408 
14409  int count = 1;
14410  bool detectPhantom = false;
14411  int dataFlags = 0;
14412  int rejectTypes = 0;
14413 
14414  for (int i = 0; i < options.Length; i += 2)
14415  {
14416  if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
14417  count = options.GetLSLIntegerItem(i + 1);
14418  else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
14419  detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
14420  else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
14421  dataFlags = options.GetLSLIntegerItem(i + 1);
14422  else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
14423  rejectTypes = options.GetLSLIntegerItem(i + 1);
14424  }
14425 
14426  if (count > 16)
14427  count = 16;
14428 
14429  List<ContactResult> results = new List<ContactResult>();
14430 
14431  bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
14432  bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
14433  bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
14434  bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
14435 
14436 
14437  if (World.SupportsRayCastFiltered())
14438  {
14439  if (dist == 0)
14440  return list;
14441 
14442  RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
14443  if (checkTerrain)
14444  rayfilter |= RayFilterFlags.land;
14445 // if (checkAgents)
14446 // rayfilter |= RayFilterFlags.agent;
14447  if (checkPhysical)
14448  rayfilter |= RayFilterFlags.physical;
14449  if (checkNonPhysical)
14450  rayfilter |= RayFilterFlags.nonphysical;
14451  if (detectPhantom)
14452  rayfilter |= RayFilterFlags.LSLPhantom;
14453 
14454  Vector3 direction = dir * ( 1/dist);
14455 
14456  if(rayfilter == 0)
14457  {
14458  list.Add(new LSL_Integer(0));
14459  return list;
14460  }
14461 
14462  // get some more contacts to sort ???
14463  int physcount = 4 * count;
14464  if (physcount > 20)
14465  physcount = 20;
14466 
14467  object physresults;
14468  physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
14469 
14470  if (physresults == null)
14471  {
14472  list.Add(new LSL_Integer(-3)); // timeout error
14473  return list;
14474  }
14475 
14476  results = (List<ContactResult>)physresults;
14477 
14478  // for now physics doesn't detect sitted avatars so do it outside physics
14479  if (checkAgents)
14480  {
14481  ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
14482  foreach (ContactResult r in agentHits)
14483  results.Add(r);
14484  }
14485 
14486  // TODO: Replace this with a better solution. ObjectIntersection can only
14487  // detect nonphysical phantoms. They are detected by virtue of being
14488  // nonphysical (e.g. no PhysActor) so will not conflict with detecting
14489  // physicsl phantoms as done by the physics scene
14490  // We don't want anything else but phantoms here.
14491  if (detectPhantom)
14492  {
14493  ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true);
14494  foreach (ContactResult r in objectHits)
14495  results.Add(r);
14496  }
14497  }
14498  else
14499  {
14500  if (checkAgents)
14501  {
14502  ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
14503  foreach (ContactResult r in agentHits)
14504  results.Add(r);
14505  }
14506 
14507  if (checkPhysical || checkNonPhysical || detectPhantom)
14508  {
14509  ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
14510  for (int iter = 0; iter < objectHits.Length; iter++)
14511  {
14512  // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler.
14513  objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart);
14514  results.Add(objectHits[iter]);
14515  }
14516  }
14517  }
14518 
14519  // Double check this
14520  if (checkTerrain)
14521  {
14522  bool skipGroundCheck = false;
14523 
14524  foreach (ContactResult c in results)
14525  {
14526  if (c.ConsumerID == 0) // Physics gave us a ground collision
14527  skipGroundCheck = true;
14528  }
14529 
14530  if (!skipGroundCheck)
14531  {
14532  ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
14533  if (groundContact != null)
14534  results.Add((ContactResult)groundContact);
14535  }
14536  }
14537 
14538  results.Sort(delegate(ContactResult a, ContactResult b)
14539  {
14540  return a.Depth.CompareTo(b.Depth);
14541  });
14542 
14543  int values = 0;
14544  SceneObjectGroup thisgrp = m_host.ParentGroup;
14545 
14546  foreach (ContactResult result in results)
14547  {
14548  if (result.Depth > dist)
14549  continue;
14550 
14551  // physics ray can return colisions with host prim
14552  if (m_host.LocalId == result.ConsumerID)
14553  continue;
14554 
14555  UUID itemID = UUID.Zero;
14556  int linkNum = 0;
14557 
14558  SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
14559  // It's a prim!
14560  if (part != null)
14561  {
14562  // dont detect members of same object ???
14563  if (part.ParentGroup == thisgrp)
14564  continue;
14565 
14566  if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
14567  itemID = part.ParentGroup.UUID;
14568  else
14569  itemID = part.UUID;
14570 
14571  linkNum = part.LinkNum;
14572  }
14573  else
14574  {
14575  ScenePresence sp = World.GetScenePresence(result.ConsumerID);
14577  if (sp != null)
14578  itemID = sp.UUID;
14579  }
14580 
14581  list.Add(new LSL_String(itemID.ToString()));
14582  list.Add(new LSL_String(result.Pos.ToString()));
14583 
14585  list.Add(new LSL_Integer(linkNum));
14586 
14587  if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
14588  list.Add(new LSL_Vector(result.Normal));
14589 
14590  values++;
14591  if (values >= count)
14592  break;
14593  }
14594 
14595  list.Add(new LSL_Integer(values));
14596 
14597  return list;
14598  }
14599 
14600 
14612  {
14613  m_host.AddScriptLPS(1);
14614  LSL_List result = new LSL_List();
14615 
14616  // Prepare throttle data
14617  int calledMs = Environment.TickCount;
14618  Stopwatch stopWatch = new Stopwatch();
14619  stopWatch.Start();
14620  UUID regionId = World.RegionInfo.RegionID;
14621  UUID userId = UUID.Zero;
14622  int msAvailable = 0;
14623  // Throttle per owner when attachment or "vehicle" (sat upon)
14624  if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatarsCount() > 0)
14625  {
14626  userId = m_host.OwnerID;
14627  msAvailable = m_msPerAvatarInCastRay;
14628  }
14629  // Throttle per parcel when not attachment or vehicle
14630  else
14631  {
14632  LandData land = World.GetLandData(m_host.GetWorldPosition());
14633  if (land != null)
14634  msAvailable = m_msPerRegionInCastRay * land.Area / 65536;
14635  }
14636  // Clamp for "oversized" parcels on varregions
14637  if (msAvailable > m_msMaxInCastRay)
14638  msAvailable = m_msMaxInCastRay;
14639 
14640  // Check throttle data
14641  int fromCalledMs = calledMs - m_msThrottleInCastRay;
14642  lock (m_castRayCalls)
14643  {
14644  for (int i = m_castRayCalls.Count - 1; i >= 0; i--)
14645  {
14646  // Delete old calls from throttle data
14647  if (m_castRayCalls[i].CalledMs < fromCalledMs)
14648  m_castRayCalls.RemoveAt(i);
14649  // Use current region (in multi-region sims)
14650  else if (m_castRayCalls[i].RegionId == regionId)
14651  {
14652  // Reduce available time with recent calls
14653  if (m_castRayCalls[i].UserId == userId)
14654  msAvailable -= m_castRayCalls[i].UsedMs;
14655  }
14656  }
14657  }
14658 
14659  // Return failure if not enough available time
14660  if (msAvailable < m_msMinInCastRay)
14661  {
14663  return result;
14664  }
14665 
14666  // Initialize
14667  List<RayHit> rayHits = new List<RayHit>();
14668  float tol = m_floatToleranceInCastRay;
14669  Vector3 pos1Ray = start;
14670  Vector3 pos2Ray = end;
14671 
14672  // Get input options
14673  int rejectTypes = 0;
14674  int dataFlags = 0;
14675  int maxHits = 1;
14676  bool detectPhantom = false;
14677  for (int i = 0; i < options.Length; i += 2)
14678  {
14679  if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
14680  rejectTypes = options.GetLSLIntegerItem(i + 1);
14681  else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
14682  dataFlags = options.GetLSLIntegerItem(i + 1);
14683  else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
14684  maxHits = options.GetLSLIntegerItem(i + 1);
14685  else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
14686  detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0);
14687  }
14688  if (maxHits > m_maxHitsInCastRay)
14689  maxHits = m_maxHitsInCastRay;
14690  bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0);
14691  bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0);
14692  bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0);
14693  bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0);
14694  bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0);
14695  bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0);
14696  bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0);
14697 
14698  // Calculate some basic parameters
14699  Vector3 vecRay = pos2Ray - pos1Ray;
14700  float rayLength = vecRay.Length();
14701 
14702  // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits
14703  IRendering primMesher = null;
14704  List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
14705  if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1)
14706  {
14707  result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN));
14708  return result;
14709  }
14710  primMesher = RenderingLoader.LoadRenderer(renderers[0]);
14711 
14712  // Iterate over all objects/groups and prims/parts in region
14713  World.ForEachSOG(
14714  delegate(SceneObjectGroup group)
14715  {
14716  // Check group filters unless part filters are configured
14717  bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical);
14718  bool isNonphysical = !isPhysical;
14719  bool isPhantom = group.IsPhantom || group.IsVolumeDetect;
14720  bool isAttachment = group.IsAttachment;
14721  bool doGroup = true;
14722  if (isPhysical && rejectPhysical)
14723  doGroup = false;
14724  if (isNonphysical && rejectNonphysical)
14725  doGroup = false;
14726  if (isPhantom && detectPhantom)
14727  doGroup = true;
14728  if (m_filterPartsInCastRay)
14729  doGroup = true;
14730  if (isAttachment && !m_doAttachmentsInCastRay)
14731  doGroup = false;
14732  // Parse object/group if passed filters
14733  if (doGroup)
14734  {
14735  // Iterate over all prims/parts in object/group
14736  foreach(SceneObjectPart part in group.Parts)
14737  {
14738  // Check part filters if configured
14739  if (m_filterPartsInCastRay)
14740  {
14741  isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical);
14742  isNonphysical = !isPhysical;
14743  isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive);
14744  bool doPart = true;
14745  if (isPhysical && rejectPhysical)
14746  doPart = false;
14747  if (isNonphysical && rejectNonphysical)
14748  doPart = false;
14749  if (isPhantom && detectPhantom)
14750  doPart = true;
14751  if (!doPart)
14752  continue;
14753  }
14754 
14755  // Parse prim/part and project ray if passed filters
14756  Vector3 scalePart = part.Scale;
14757  Vector3 posPart = part.GetWorldPosition();
14758  Quaternion rotPart = part.GetWorldRotation();
14759  Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14760  Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14761  Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14762 
14763  // Filter parts by shape bounding boxes
14764  Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f);
14765  if (!part.Shape.SculptEntry)
14766  shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ));
14767  shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol));
14768  if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14769  {
14770  // Prepare data needed to check for ray hits
14771  RayTrans rayTrans = new RayTrans();
14772  rayTrans.PartId = part.UUID;
14773  rayTrans.GroupId = part.ParentGroup.UUID;
14774  rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0;
14775  rayTrans.ScalePart = scalePart;
14776  rayTrans.PositionPart = posPart;
14777  rayTrans.RotationPart = rotPart;
14778  rayTrans.ShapeNeedsEnds = true;
14779  rayTrans.Position1Ray = pos1Ray;
14780  rayTrans.Position1RayProj = pos1RayProj;
14781  rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14782 
14783  // Get detail level depending on type
14784  int lod = 0;
14785  // Mesh detail level
14786  if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14787  lod = (int)m_meshLodInCastRay;
14788  // Sculpt detail level
14789  else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14790  lod = (int)m_sculptLodInCastRay;
14791  // Shape detail level
14792  else if (!part.Shape.SculptEntry)
14793  lod = (int)m_primLodInCastRay;
14794 
14795  // Try to get cached mesh if configured
14796  ulong meshKey = 0;
14797  FacetedMesh mesh = null;
14798  if (m_useMeshCacheInCastRay)
14799  {
14800  meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod));
14801  lock (m_cachedMeshes)
14802  {
14803  m_cachedMeshes.TryGetValue(meshKey, out mesh);
14804  }
14805  }
14806 
14807  // Create mesh if no cached mesh
14808  if (mesh == null)
14809  {
14810  // Make an OMV prim to be able to mesh part
14811  Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart);
14812  byte[] sculptAsset = null;
14813  if (omvPrim.Sculpt != null)
14814  sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
14815 
14816  // When part is mesh, get mesh
14817  if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
14818  {
14819  AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
14820  FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
14821  meshAsset = null;
14822  }
14823 
14824  // When part is sculpt, create mesh
14825  // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
14826  else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
14827  {
14828  IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
14829  if (imgDecoder != null)
14830  {
14831  Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
14832  if (sculpt != null)
14833  {
14834  mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
14835  sculpt.Dispose();
14836  }
14837  }
14838  }
14839 
14840  // When part is shape, create mesh
14841  else if (omvPrim.Sculpt == null)
14842  {
14843  if (
14844  omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 &&
14845  omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 &&
14846  omvPrim.PrimData.PathSkew == 0.0 &&
14847  omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
14848  )
14849  rayTrans.ShapeNeedsEnds = false;
14850  mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
14851  }
14852 
14853  // Cache mesh if configured
14854  if (m_useMeshCacheInCastRay && mesh != null)
14855  {
14856  lock(m_cachedMeshes)
14857  {
14858  if (!m_cachedMeshes.ContainsKey(meshKey))
14859  m_cachedMeshes.Add(meshKey, mesh);
14860  }
14861  }
14862  }
14863  // Check mesh for ray hits
14864  AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14865  mesh = null;
14866  }
14867  }
14868  }
14869  }
14870  );
14871 
14872  // Check avatar filter
14873  if (!rejectAgents)
14874  {
14875  // Iterate over all avatars in region
14876  World.ForEachRootScenePresence(
14877  delegate (ScenePresence sp)
14878  {
14879  // Get bounding box
14880  Vector3 lower;
14881  Vector3 upper;
14882  BoundingBoxOfScenePresence(sp, out lower, out upper);
14883  // Parse avatar
14884  Vector3 scalePart = upper - lower;
14885  Vector3 posPart = sp.AbsolutePosition;
14886  Quaternion rotPart = sp.GetWorldRotation();
14887  Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14888  posPart = posPart + (lower + upper) * 0.5f * rotPart;
14889  // Project ray
14890  Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14891  Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14892 
14893  // Filter avatars by shape bounding boxes
14894  Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol);
14895  if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14896  {
14897  // Prepare data needed to check for ray hits
14898  RayTrans rayTrans = new RayTrans();
14899  rayTrans.PartId = sp.UUID;
14900  rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID;
14901  rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0;
14902  rayTrans.ScalePart = scalePart;
14903  rayTrans.PositionPart = posPart;
14904  rayTrans.RotationPart = rotPart;
14905  rayTrans.ShapeNeedsEnds = false;
14906  rayTrans.Position1Ray = pos1Ray;
14907  rayTrans.Position1RayProj = pos1RayProj;
14908  rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14909 
14910  // Try to get cached mesh if configured
14911  PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere();
14912  int lod = (int)m_avatarLodInCastRay;
14913  ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod));
14914  FacetedMesh mesh = null;
14915  if (m_useMeshCacheInCastRay)
14916  {
14917  lock (m_cachedMeshes)
14918  {
14919  m_cachedMeshes.TryGetValue(meshKey, out mesh);
14920  }
14921  }
14922 
14923  // Create mesh if no cached mesh
14924  if (mesh == null)
14925  {
14926  // Make OMV prim and create mesh
14927  prim.Scale = scalePart;
14928  Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart);
14929  mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay);
14930 
14931  // Cache mesh if configured
14932  if (m_useMeshCacheInCastRay && mesh != null)
14933  {
14934  lock(m_cachedMeshes)
14935  {
14936  if (!m_cachedMeshes.ContainsKey(meshKey))
14937  m_cachedMeshes.Add(meshKey, mesh);
14938  }
14939  }
14940  }
14941 
14942  // Check mesh for ray hits
14943  AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14944  mesh = null;
14945  }
14946  }
14947  );
14948  }
14949 
14950  // Check terrain filter
14951  if (!rejectLand)
14952  {
14953  // Parse terrain
14954 
14955  // Mesh terrain and check bounding box
14956  Vector3 lower;
14957  Vector3 upper;
14958  List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper);
14959  lower.Z -= tol;
14960  upper.Z += tol;
14961  if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z))
14962  {
14963  // Prepare data needed to check for ray hits
14964  RayTrans rayTrans = new RayTrans();
14965  rayTrans.PartId = UUID.Zero;
14966  rayTrans.GroupId = UUID.Zero;
14967  rayTrans.Link = 0;
14968  rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f);
14969  rayTrans.PositionPart = Vector3.Zero;
14970  rayTrans.RotationPart = Quaternion.Identity;
14971  rayTrans.ShapeNeedsEnds = true;
14972  rayTrans.Position1Ray = pos1Ray;
14973  rayTrans.Position1RayProj = pos1Ray;
14974  rayTrans.VectorRayProj = vecRay;
14975 
14976  // Check mesh
14977  AddRayInTris(triangles, rayTrans, ref rayHits);
14978  triangles = null;
14979  }
14980  }
14981 
14982  // Sort hits by ascending distance
14983  rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance));
14984 
14985  // Check excess hits per part and group
14986  for (int t = 0; t < 2; t++)
14987  {
14988  int maxHitsPerType = 0;
14989  UUID id = UUID.Zero;
14990  if (t == 0)
14991  maxHitsPerType = m_maxHitsPerPrimInCastRay;
14992  else
14993  maxHitsPerType = m_maxHitsPerObjectInCastRay;
14994 
14995  // Handle excess hits only when needed
14996  if (maxHitsPerType < m_maxHitsInCastRay)
14997  {
14998  // Find excess hits
14999  Hashtable hits = new Hashtable();
15000  for (int i = rayHits.Count - 1; i >= 0; i--)
15001  {
15002  if (t == 0)
15003  id = rayHits[i].PartId;
15004  else
15005  id = rayHits[i].GroupId;
15006  if (hits.ContainsKey(id))
15007  hits[id] = (int)hits[id] + 1;
15008  else
15009  hits[id] = 1;
15010  }
15011 
15012  // Remove excess hits
15013  for (int i = rayHits.Count - 1; i >= 0; i--)
15014  {
15015  if (t == 0)
15016  id = rayHits[i].PartId;
15017  else
15018  id = rayHits[i].GroupId;
15019  int hit = (int)hits[id];
15020  if (hit > m_maxHitsPerPrimInCastRay)
15021  {
15022  rayHits.RemoveAt(i);
15023  hit--;
15024  hits[id] = hit;
15025  }
15026  }
15027  }
15028  }
15029 
15030  // Parse hits into result list according to data flags
15031  int hitCount = rayHits.Count;
15032  if (hitCount > maxHits)
15033  hitCount = maxHits;
15034  for (int i = 0; i < hitCount; i++)
15035  {
15036  RayHit rayHit = rayHits[i];
15037  if (getRootKey)
15038  result.Add(new LSL_Key(rayHit.GroupId.ToString()));
15039  else
15040  result.Add(new LSL_Key(rayHit.PartId.ToString()));
15041  result.Add(new LSL_Vector(rayHit.Position));
15042  if (getLinkNum)
15043  result.Add(new LSL_Integer(rayHit.Link));
15044  if (getNormal)
15045  result.Add(new LSL_Vector(rayHit.Normal));
15046  }
15047  result.Add(new LSL_Integer(hitCount));
15048 
15049  // Add to throttle data
15050  stopWatch.Stop();
15051  CastRayCall castRayCall = new CastRayCall();
15052  castRayCall.RegionId = regionId;
15053  castRayCall.UserId = userId;
15054  castRayCall.CalledMs = calledMs;
15055  castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds;
15056  lock (m_castRayCalls)
15057  {
15058  m_castRayCalls.Add(castRayCall);
15059  }
15060 
15061  // Return hits
15062  return result;
15063  }
15064 
15068  public struct RayTrans
15069  {
15070  public UUID PartId;
15071  public UUID GroupId;
15072  public int Link;
15073  public Vector3 ScalePart;
15074  public Vector3 PositionPart;
15075  public Quaternion RotationPart;
15076  public bool ShapeNeedsEnds;
15077  public Vector3 Position1Ray;
15078  public Vector3 Position1RayProj;
15079  public Vector3 VectorRayProj;
15080  }
15081 
15085  public struct RayHit
15086  {
15087  public UUID PartId;
15088  public UUID GroupId;
15089  public int Link;
15090  public Vector3 Position;
15091  public Vector3 Normal;
15092  public float Distance;
15093  }
15094 
15098  public struct CastRayCall
15099  {
15100  public UUID RegionId;
15101  public UUID UserId;
15102  public int CalledMs;
15103  public int UsedMs;
15104  }
15105 
15109  private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax)
15110  {
15111  // Skip if ray can't intersect bounding box;
15112  Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj);
15113  Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj);
15114  if (
15115  rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z ||
15116  rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z
15117  )
15118  return false;
15119 
15120  // Check if ray intersect any bounding box side
15121  int sign = 0;
15122  float dist = 0.0f;
15123  Vector3 posProj = Vector3.Zero;
15124  Vector3 vecRayProj = pos2RayProj - pos1RayProj;
15125 
15126  // Check both X sides unless ray is parallell to them
15127  if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay)
15128  {
15129  for (sign = -1; sign <= 1; sign += 2)
15130  {
15131  dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X;
15132  posProj = pos1RayProj + vecRayProj * dist;
15133  if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
15134  return true;
15135  }
15136  }
15137 
15138  // Check both Y sides unless ray is parallell to them
15139  if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay)
15140  {
15141  for (sign = -1; sign <= 1; sign += 2)
15142  {
15143  dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y;
15144  posProj = pos1RayProj + vecRayProj * dist;
15145  if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
15146  return true;
15147  }
15148  }
15149 
15150  // Check both Z sides unless ray is parallell to them
15151  if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay)
15152  {
15153  for (sign = -1; sign <= 1; sign += 2)
15154  {
15155  dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z;
15156  posProj = pos1RayProj + vecRayProj * dist;
15157  if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y)
15158  return true;
15159  }
15160  }
15161 
15162  // No hits on bounding box so return false
15163  return false;
15164  }
15165 
15169  private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits)
15170  {
15171  if (mesh != null)
15172  {
15173  foreach (Face face in mesh.Faces)
15174  {
15175  for (int i = 0; i < face.Indices.Count; i += 3)
15176  {
15177  Tri triangle = new Tri();
15178  triangle.p1 = face.Vertices[face.Indices[i]].Position;
15179  triangle.p2 = face.Vertices[face.Indices[i + 1]].Position;
15180  triangle.p3 = face.Vertices[face.Indices[i + 2]].Position;
15181  AddRayInTri(triangle, rayTrans, ref rayHits);
15182  }
15183  }
15184  }
15185  }
15186 
15190  private void AddRayInTris(List<Tri> triangles, RayTrans rayTrans, ref List<RayHit> rayHits)
15191  {
15192  foreach (Tri triangle in triangles)
15193  {
15194  AddRayInTri(triangle, rayTrans, ref rayHits);
15195  }
15196  }
15197 
15201  private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits)
15202  {
15203  // Check for hit in triangle
15204  Vector3 posHitProj;
15205  Vector3 normalProj;
15206  if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj))
15207  {
15208  // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center
15209  if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds)
15210  return;
15211 
15212  // Transform hit and normal to region coordinate system
15213  Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart;
15214  Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart);
15215 
15216  // Remove duplicate hits at triangle intersections
15217  float distance = Vector3.Distance(rayTrans.Position1Ray, posHit);
15218  for (int i = rayHits.Count - 1; i >= 0; i--)
15219  {
15220  if (rayHits[i].PartId != rayTrans.PartId)
15221  break;
15222  if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay)
15223  return;
15224  }
15225 
15226  // Build result data set
15227  RayHit rayHit = new RayHit();
15228  rayHit.PartId = rayTrans.PartId;
15229  rayHit.GroupId = rayTrans.GroupId;
15230  rayHit.Link = rayTrans.Link;
15231  rayHit.Position = posHit;
15232  rayHit.Normal = normal;
15233  rayHit.Distance = distance;
15234  rayHits.Add(rayHit);
15235  }
15236  }
15237 
15241  bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj)
15242  {
15243  float tol = m_floatToleranceInCastRay;
15244  posHitProj = Vector3.Zero;
15245 
15246  // Calculate triangle edge vectors
15247  Vector3 vec1Proj = triProj.p2 - triProj.p1;
15248  Vector3 vec2Proj = triProj.p3 - triProj.p2;
15249  Vector3 vec3Proj = triProj.p1 - triProj.p3;
15250 
15251  // Calculate triangle normal
15252  normalProj = Vector3.Cross(vec1Proj, vec2Proj);
15253 
15254  // Skip if degenerate triangle or ray parallell with triangle plane
15255  float divisor = Vector3.Dot(vecRayProj, normalProj);
15256  if (Math.Abs(divisor) < tol)
15257  return false;
15258 
15259  // Skip if exit and not configured to detect
15260  if (divisor > tol && !m_detectExitsInCastRay)
15261  return false;
15262 
15263  // Skip if outside ray ends
15264  float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor;
15265  if (distanceProj < -tol || distanceProj > 1 + tol)
15266  return false;
15267 
15268  // Calculate hit position in triangle
15269  posHitProj = pos1RayProj + vecRayProj * distanceProj;
15270 
15271  // Skip if outside triangle bounding box
15272  Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3);
15273  Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3);
15274  if (
15275  posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol ||
15276  posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol
15277  )
15278  return false;
15279 
15280  // Skip if outside triangle
15281  if (
15282  Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol ||
15283  Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol ||
15284  Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol
15285  )
15286  return false;
15287 
15288  // Return hit
15289  return true;
15290  }
15291 
15295  private List<Tri> TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper)
15296  {
15297  // Get bounding X-Y rectangle of terrain under ray
15298  lower = Vector3.Min(posStart, posEnd);
15299  upper = Vector3.Max(posStart, posEnd);
15300  lower.X = (float)Math.Floor(lower.X);
15301  lower.Y = (float)Math.Floor(lower.Y);
15302  float zLower = float.MaxValue;
15303  upper.X = (float)Math.Ceiling(upper.X);
15304  upper.Y = (float)Math.Ceiling(upper.Y);
15305  float zUpper = float.MinValue;
15306 
15307  // Initialize Tri (triangle) List
15308  List<Tri> triangles = new List<Tri>();
15309 
15310  // Set parsing lane direction to major ray X-Y axis
15311  Vector3 vec = posEnd - posStart;
15312  float xAbs = Math.Abs(vec.X);
15313  float yAbs = Math.Abs(vec.Y);
15314  bool bigX = true;
15315  if (yAbs > xAbs)
15316  {
15317  bigX = false;
15318  vec = vec / yAbs;
15319  }
15320  else if (xAbs > yAbs || xAbs > 0.0f)
15321  vec = vec / xAbs;
15322  else
15323  vec = new Vector3(1.0f, 1.0f, 0.0f);
15324 
15325  // Simplify by start parsing in lower end of lane
15326  if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f))
15327  {
15328  Vector3 posTemp = posStart;
15329  posStart = posEnd;
15330  posEnd = posTemp;
15331  vec = vec * -1.0f;
15332  }
15333 
15334  // First 1x1 rectangle under ray
15335  float xFloorOld = 0.0f;
15336  float yFloorOld = 0.0f;
15337  Vector3 pos = posStart;
15338  float xFloor = (float)Math.Floor(pos.X);
15339  float yFloor = (float)Math.Floor(pos.Y);
15340  AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper);
15341 
15342  // Parse every remaining 1x1 rectangle under ray
15343  while (pos != posEnd)
15344  {
15345  // Next 1x1 rectangle under ray
15346  xFloorOld = xFloor;
15347  yFloorOld = yFloor;
15348  pos = pos + vec;
15349 
15350  // Clip position to 1x1 rectangle border
15351  xFloor = (float)Math.Floor(pos.X);
15352  yFloor = (float)Math.Floor(pos.Y);
15353  if (bigX && pos.X > xFloor)
15354  {
15355  pos.Y -= vec.Y * (pos.X - xFloor);
15356  pos.X = xFloor;
15357  }
15358  else if (!bigX && pos.Y > yFloor)
15359  {
15360  pos.X -= vec.X * (pos.Y - yFloor);
15361  pos.Y = yFloor;
15362  }
15363 
15364  // Last 1x1 rectangle under ray
15365  if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y))
15366  {
15367  pos = posEnd;
15368  xFloor = (float)Math.Floor(pos.X);
15369  yFloor = (float)Math.Floor(pos.Y);
15370  }
15371 
15372  // Add new 1x1 rectangle in lane
15373  if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld))
15374  AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper);
15375  // Add last 1x1 rectangle in old lane at lane shift
15376  if (bigX && yFloor != yFloorOld)
15377  AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper);
15378  if (!bigX && xFloor != xFloorOld)
15379  AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper);
15380  }
15381 
15382  // Finalize bounding box Z
15383  lower.Z = zLower;
15384  upper.Z = zUpper;
15385 
15386  // Done and returning Tri (triangle)List
15387  return triangles;
15388  }
15389 
15393  private void AddTrisFromHeightmap(float xPos, float yPos, ref List<Tri> triangles, ref float zLower, ref float zUpper)
15394  {
15395  int xInt = (int)xPos;
15396  int yInt = (int)yPos;
15397 
15398  // Corner 1 of 1x1 rectangle
15399  int x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
15400  int y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
15401  Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]);
15402  // Adjust bounding box
15403  zLower = Math.Min(zLower, pos1.Z);
15404  zUpper = Math.Max(zUpper, pos1.Z);
15405 
15406  // Corner 2 of 1x1 rectangle
15407  x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
15408  y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
15409  Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]);
15410  // Adjust bounding box
15411  zLower = Math.Min(zLower, pos2.Z);
15412  zUpper = Math.Max(zUpper, pos2.Z);
15413 
15414  // Corner 3 of 1x1 rectangle
15415  x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
15416  y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
15417  Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]);
15418  // Adjust bounding box
15419  zLower = Math.Min(zLower, pos3.Z);
15420  zUpper = Math.Max(zUpper, pos3.Z);
15421 
15422  // Corner 4 of 1x1 rectangle
15423  x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
15424  y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
15425  Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]);
15426  // Adjust bounding box
15427  zLower = Math.Min(zLower, pos4.Z);
15428  zUpper = Math.Max(zUpper, pos4.Z);
15429 
15430  // Add triangle 1
15431  Tri triangle1 = new Tri();
15432  triangle1.p1 = pos1;
15433  triangle1.p2 = pos2;
15434  triangle1.p3 = pos3;
15435  triangles.Add(triangle1);
15436 
15437  // Add triangle 2
15438  Tri triangle2 = new Tri();
15439  triangle2.p1 = pos3;
15440  triangle2.p2 = pos4;
15441  triangle2.p3 = pos1;
15442  triangles.Add(triangle2);
15443  }
15444 
15448  private int UUID2LinkNumber(SceneObjectPart part, UUID id)
15449  {
15450  SceneObjectGroup group = part.ParentGroup;
15451  if (group != null)
15452  {
15453  // Parse every link for UUID
15454  int linkCount = group.PrimCount + group.GetSittingAvatarsCount();
15455  for (int link = linkCount; link > 0; link--)
15456  {
15457  ISceneEntity entity = GetLinkEntity(part, link);
15458  // Return link number if UUID match
15459  if (entity != null && entity.UUID == id)
15460  return link;
15461  }
15462  }
15463  // Return link number 0 if no links or UUID matches
15464  return 0;
15465  }
15466 
15467  public LSL_Integer llManageEstateAccess(int action, string avatar)
15468  {
15469  m_host.AddScriptLPS(1);
15470  EstateSettings estate = World.RegionInfo.EstateSettings;
15471  bool isAccount = false;
15472  bool isGroup = false;
15473 
15474  if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManagerOrOwner(m_host.OwnerID))
15475  return 0;
15476 
15477  UUID id = new UUID();
15478  if (!UUID.TryParse(avatar, out id))
15479  return 0;
15480 
15481  UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, id);
15482  isAccount = account != null ? true : false;
15483  if (!isAccount)
15484  {
15485  IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
15486  if (groups != null)
15487  {
15488  GroupRecord group = groups.GetGroupRecord(id);
15489  isGroup = group != null ? true : false;
15490  if (!isGroup)
15491  return 0;
15492  }
15493  else
15494  return 0;
15495  }
15496 
15497  switch (action)
15498  {
15499  case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
15500  if (!isAccount) return 0;
15501  if (estate.HasAccess(id)) return 1;
15502  if (estate.IsBanned(id, World.GetUserFlags(id)))
15503  estate.RemoveBan(id);
15504  estate.AddEstateUser(id);
15505  break;
15506  case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_REMOVE:
15507  if (!isAccount || !estate.HasAccess(id)) return 0;
15508  estate.RemoveEstateUser(id);
15509  break;
15510  case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_ADD:
15511  if (!isGroup) return 0;
15512  if (estate.GroupAccess(id)) return 1;
15513  estate.AddEstateGroup(id);
15514  break;
15515  case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_REMOVE:
15516  if (!isGroup || !estate.GroupAccess(id)) return 0;
15517  estate.RemoveEstateGroup(id);
15518  break;
15519  case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
15520  if (!isAccount) return 0;
15521  if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
15522  EstateBan ban = new EstateBan();
15523  ban.EstateID = estate.EstateID;
15524  ban.BannedUserID = id;
15525  estate.AddBan(ban);
15526  break;
15527  case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
15528  if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
15529  estate.RemoveBan(id);
15530  break;
15531  default: return 0;
15532  }
15533  return 1;
15534  }
15535 
15537  {
15538  m_host.AddScriptLPS(1);
15539  // The value returned for Mono scripts in SL
15540  return 65536;
15541  }
15542 
15544  {
15545  m_host.AddScriptLPS(1);
15546  // Treat as an LSO script
15547  return ScriptBaseClass.FALSE;
15548  }
15549 
15551  {
15552  m_host.AddScriptLPS(1);
15553  // The value returned for Mono scripts in SL
15554  return 65536;
15555  }
15556 
15557  public virtual LSL_Integer llGetUsedMemory()
15558  {
15559  m_host.AddScriptLPS(1);
15560  // The value returned for Mono scripts in SL
15561  return 65536;
15562  }
15563 
15564  public void llScriptProfiler(LSL_Integer flags)
15565  {
15566  m_host.AddScriptLPS(1);
15567  // This does nothing for LSO scripts in SL
15568  }
15569 
15570  #region Not Implemented
15571  //
15572  // Listing the unimplemented lsl functions here, please move
15573  // them from this region as they are completed
15574  //
15575 
15576  public void llSetSoundQueueing(int queue)
15577  {
15578  m_host.AddScriptLPS(1);
15579 
15580  if (m_SoundModule != null)
15581  m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value);
15582  }
15583 
15584  public void llCollisionSprite(string impact_sprite)
15585  {
15586  m_host.AddScriptLPS(1);
15587  // Viewer 2.0 broke this and it's likely LL has no intention
15588  // of fixing it. Therefore, letting this be a NOP seems appropriate.
15589  }
15590 
15591  public void llGodLikeRezObject(string inventory, LSL_Vector pos)
15592  {
15593  m_host.AddScriptLPS(1);
15594 
15595  if (!World.Permissions.IsGod(m_host.OwnerID))
15596  NotImplemented("llGodLikeRezObject");
15597 
15598  AssetBase rezAsset = World.AssetService.Get(inventory);
15599  if (rezAsset == null)
15600  {
15601  llSay(0, "Asset not found");
15602  return;
15603  }
15604 
15605  SceneObjectGroup group = null;
15606 
15607  try
15608  {
15609  string xmlData = Utils.BytesToString(rezAsset.Data);
15610  group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
15611  }
15612  catch
15613  {
15614  llSay(0, "Asset not found");
15615  return;
15616  }
15617 
15618  if (group == null)
15619  {
15620  llSay(0, "Asset not found");
15621  return;
15622  }
15623 
15624  group.RootPart.AttachPoint = group.RootPart.Shape.State;
15625  group.RootPart.AttachedPos = group.AbsolutePosition;
15626 
15627  group.ResetIDs();
15628 
15629  Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
15630  World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
15631  group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
15632  group.ScheduleGroupForFullUpdate();
15633 
15634  // objects rezzed with this method are die_at_edge by default.
15635  group.RootPart.SetDieAtEdge(true);
15636 
15637  group.ResumeScripts();
15638 
15639  m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
15640  "object_rez", new Object[] {
15641  new LSL_String(
15642  group.RootPart.UUID.ToString()) },
15643  new DetectParams[0]));
15644  }
15645 
15646  public LSL_String llTransferLindenDollars(string destination, int amount)
15647  {
15648  UUID txn = UUID.Random();
15649 
15650  Util.FireAndForget(delegate(object x)
15651  {
15652  int replycode = 0;
15653  string replydata = destination + "," + amount.ToString();
15654 
15655  try
15656  {
15657  TaskInventoryItem item = m_item;
15658  if (item == null)
15659  {
15660  replydata = "SERVICE_ERROR";
15661  return;
15662  }
15663 
15664  m_host.AddScriptLPS(1);
15665 
15666  if (item.PermsGranter == UUID.Zero)
15667  {
15668  replydata = "MISSING_PERMISSION_DEBIT";
15669  return;
15670  }
15671 
15672  if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
15673  {
15674  replydata = "MISSING_PERMISSION_DEBIT";
15675  return;
15676  }
15677 
15678  UUID toID = new UUID();
15679 
15680  if (!UUID.TryParse(destination, out toID))
15681  {
15682  replydata = "INVALID_AGENT";
15683  return;
15684  }
15685 
15686  IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
15687 
15688  if (money == null)
15689  {
15690  replydata = "TRANSFERS_DISABLED";
15691  return;
15692  }
15693 
15694  string reason;
15695  bool result = money.ObjectGiveMoney(
15696  m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn, out reason);
15697 
15698  if (result)
15699  {
15700  replycode = 1;
15701  return;
15702  }
15703 
15704  replydata = reason;
15705  }
15706  finally
15707  {
15708  m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
15709  "transaction_result", new Object[] {
15710  new LSL_String(txn.ToString()),
15711  new LSL_Integer(replycode),
15712  new LSL_String(replydata) },
15713  new DetectParams[0]));
15714  }
15715  }, null, "LSL_Api.llTransferLindenDollars");
15716 
15717  return txn.ToString();
15718  }
15719 
15720  #endregion
15721 
15722 
15723  protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
15724  {
15725  //This is a special version of SetPrimParams to deal with avatars which are sitting on the linkset.
15726 
15727  int idx = 0;
15728  int idxStart = 0;
15729 
15730  bool positionChanged = false;
15731  try
15732  {
15733  while (idx < rules.Length)
15734  {
15735  ++rulesParsed;
15736  int code = rules.GetLSLIntegerItem(idx++);
15737 
15738  int remain = rules.Length - idx;
15739  idxStart = idx;
15740 
15741  switch (code)
15742  {
15743  case (int)ScriptBaseClass.PRIM_POSITION:
15744  case (int)ScriptBaseClass.PRIM_POS_LOCAL:
15745  {
15746  if (remain < 1)
15747  return new LSL_List();
15748 
15749  LSL_Vector v;
15750  v = rules.GetVector3Item(idx++);
15751 
15752  if(!av.LegacySitOffsets)
15753  {
15754  LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
15755 
15756  v = v + 2 * sitOffset;
15757  }
15758 
15759  av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
15760  positionChanged = true;
15761  }
15762  break;
15763 
15764  case (int)ScriptBaseClass.PRIM_ROTATION:
15765  {
15766  if (remain < 1)
15767  return new LSL_List();
15768 
15769  Quaternion r;
15770  r = rules.GetQuaternionItem(idx++);
15771 
15772  av.Rotation = m_host.GetWorldRotation() * r;
15773  positionChanged = true;
15774  }
15775  break;
15776 
15777  case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
15778  {
15779  if (remain < 1)
15780  return new LSL_List();
15781 
15782  LSL_Rotation r;
15783  r = rules.GetQuaternionItem(idx++);
15784 
15785  av.Rotation = r;
15786  positionChanged = true;
15787  }
15788  break;
15789 
15790  // parse rest doing nothing but number of parameters error check
15791  case (int)ScriptBaseClass.PRIM_SIZE:
15792  case (int)ScriptBaseClass.PRIM_MATERIAL:
15793  case (int)ScriptBaseClass.PRIM_PHANTOM:
15794  case (int)ScriptBaseClass.PRIM_PHYSICS:
15795  case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
15796  case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
15797  case (int)ScriptBaseClass.PRIM_NAME:
15798  case (int)ScriptBaseClass.PRIM_DESC:
15799  if (remain < 1)
15800  return new LSL_List();
15801  idx++;
15802  break;
15803 
15804  case (int)ScriptBaseClass.PRIM_GLOW:
15805  case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
15806  case (int)ScriptBaseClass.PRIM_TEXGEN:
15807  if (remain < 2)
15808  return new LSL_List();
15809  idx += 2;
15810  break;
15811 
15812  case (int)ScriptBaseClass.PRIM_TYPE:
15813  if (remain < 3)
15814  return new LSL_List();
15815  code = (int)rules.GetLSLIntegerItem(idx++);
15816  remain = rules.Length - idx;
15817  switch (code)
15818  {
15819  case (int)ScriptBaseClass.PRIM_TYPE_BOX:
15820  case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
15821  case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
15822  if (remain < 6)
15823  return new LSL_List();
15824  idx += 6;
15825  break;
15826 
15827  case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
15828  if (remain < 5)
15829  return new LSL_List();
15830  idx += 5;
15831  break;
15832 
15833  case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
15834  case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
15835  case (int)ScriptBaseClass.PRIM_TYPE_RING:
15836  if (remain < 11)
15837  return new LSL_List();
15838  idx += 11;
15839  break;
15840 
15841  case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
15842  if (remain < 2)
15843  return new LSL_List();
15844  idx += 2;
15845  break;
15846  }
15847  break;
15848 
15849  case (int)ScriptBaseClass.PRIM_COLOR:
15850  case (int)ScriptBaseClass.PRIM_TEXT:
15851  case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
15852  case (int)ScriptBaseClass.PRIM_OMEGA:
15853  if (remain < 3)
15854  return new LSL_List();
15855  idx += 3;
15856  break;
15857 
15858  case (int)ScriptBaseClass.PRIM_TEXTURE:
15859  case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
15860  case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
15861  if (remain < 5)
15862  return new LSL_List();
15863  idx += 5;
15864  break;
15865 
15866  case (int)ScriptBaseClass.PRIM_FLEXIBLE:
15867  if (remain < 7)
15868  return new LSL_List();
15869 
15870  idx += 7;
15871  break;
15872 
15873  case (int)ScriptBaseClass.PRIM_LINK_TARGET:
15874  if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
15875  return new LSL_List();
15876 
15877  return rules.GetSublist(idx, -1);
15878  }
15879  }
15880  }
15881  catch (InvalidCastException e)
15882  {
15883  Error(originFunc,string.Format(
15884  " error running rule #{1}: arg #{2} ",
15885  rulesParsed, idx - idxStart) + e.Message);
15886  }
15887  finally
15888  {
15889  if (positionChanged)
15890  av.SendTerseUpdateToAllClients();
15891  }
15892  return new LSL_List();
15893  }
15894 
15895  public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
15896  {
15897  // avatars case
15898  // replies as SL wiki
15899 
15900 // SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
15901  SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
15902 
15903  int idx = 0;
15904  while (idx < rules.Length)
15905  {
15906  int code = (int)rules.GetLSLIntegerItem(idx++);
15907  int remain = rules.Length - idx;
15908 
15909  switch (code)
15910  {
15911  case (int)ScriptBaseClass.PRIM_MATERIAL:
15912  res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
15913  break;
15914 
15915  case (int)ScriptBaseClass.PRIM_PHYSICS:
15916  res.Add(new LSL_Integer(0));
15917  break;
15918 
15919  case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
15920  res.Add(new LSL_Integer(0));
15921  break;
15922 
15923  case (int)ScriptBaseClass.PRIM_PHANTOM:
15924  res.Add(new LSL_Integer(0));
15925  break;
15926 
15927  case (int)ScriptBaseClass.PRIM_POSITION:
15928  Vector3 pos;
15929 
15930  if (sitPart.ParentGroup.RootPart != null)
15931  {
15932  pos = avatar.OffsetPosition;
15933 
15934  if(!avatar.LegacySitOffsets)
15935  {
15936  Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
15937  pos -= sitOffset;
15938  }
15939 
15940  SceneObjectPart sitroot = sitPart.ParentGroup.RootPart;
15941  pos = sitroot.AbsolutePosition + pos * sitroot.GetWorldRotation();
15942  }
15943  else
15944  pos = avatar.AbsolutePosition;
15945 
15946  res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
15947  break;
15948 
15949  case (int)ScriptBaseClass.PRIM_SIZE:
15950  Vector3 s = avatar.Appearance.AvatarSize;
15951  res.Add(new LSL_Vector(s.X, s.Y, s.Z));
15952 
15953  break;
15954 
15955  case (int)ScriptBaseClass.PRIM_ROTATION:
15956  res.Add(new LSL_Rotation(avatar.GetWorldRotation()));
15957  break;
15958 
15959  case (int)ScriptBaseClass.PRIM_TYPE:
15962  res.Add(new LSL_Vector(0f,1.0f,0f));
15963  res.Add(new LSL_Float(0.0f));
15964  res.Add(new LSL_Vector(0, 0, 0));
15965  res.Add(new LSL_Vector(1.0f,1.0f,0f));
15966  res.Add(new LSL_Vector(0, 0, 0));
15967  break;
15968 
15969  case (int)ScriptBaseClass.PRIM_TEXTURE:
15970  if (remain < 1)
15971  return new LSL_List();
15972 
15973  int face = (int)rules.GetLSLIntegerItem(idx++);
15974  if (face == ScriptBaseClass.ALL_SIDES)
15975  {
15976  for (face = 0; face < 21; face++)
15977  {
15978  res.Add(new LSL_String(""));
15979  res.Add(new LSL_Vector(0,0,0));
15980  res.Add(new LSL_Vector(0,0,0));
15981  res.Add(new LSL_Float(0.0));
15982  }
15983  }
15984  else
15985  {
15986  if (face >= 0 && face < 21)
15987  {
15988  res.Add(new LSL_String(""));
15989  res.Add(new LSL_Vector(0,0,0));
15990  res.Add(new LSL_Vector(0,0,0));
15991  res.Add(new LSL_Float(0.0));
15992  }
15993  }
15994  break;
15995 
15996  case (int)ScriptBaseClass.PRIM_COLOR:
15997  if (remain < 1)
15998  return new LSL_List();
15999 
16000  face = (int)rules.GetLSLIntegerItem(idx++);
16001 
16002  if (face == ScriptBaseClass.ALL_SIDES)
16003  {
16004  for (face = 0; face < 21; face++)
16005  {
16006  res.Add(new LSL_Vector(0,0,0));
16007  res.Add(new LSL_Float(0));
16008  }
16009  }
16010  else
16011  {
16012  res.Add(new LSL_Vector(0,0,0));
16013  res.Add(new LSL_Float(0));
16014  }
16015  break;
16016 
16017  case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
16018  if (remain < 1)
16019  return new LSL_List();
16020  face = (int)rules.GetLSLIntegerItem(idx++);
16021 
16022  if (face == ScriptBaseClass.ALL_SIDES)
16023  {
16024  for (face = 0; face < 21; face++)
16025  {
16028  }
16029  }
16030  else
16031  {
16034  }
16035  break;
16036 
16037  case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
16038  if (remain < 1)
16039  return new LSL_List();
16040  face = (int)rules.GetLSLIntegerItem(idx++);
16041 
16042  if (face == ScriptBaseClass.ALL_SIDES)
16043  {
16044  for (face = 0; face < 21; face++)
16045  {
16046  res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
16047  }
16048  }
16049  else
16050  {
16051  res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
16052  }
16053  break;
16054 
16055  case (int)ScriptBaseClass.PRIM_FLEXIBLE:
16056  res.Add(new LSL_Integer(0));
16057  res.Add(new LSL_Integer(0));// softness
16058  res.Add(new LSL_Float(0.0f)); // gravity
16059  res.Add(new LSL_Float(0.0f)); // friction
16060  res.Add(new LSL_Float(0.0f)); // wind
16061  res.Add(new LSL_Float(0.0f)); // tension
16062  res.Add(new LSL_Vector(0f,0f,0f));
16063  break;
16064 
16065  case (int)ScriptBaseClass.PRIM_TEXGEN:
16066  // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
16067  if (remain < 1)
16068  return new LSL_List();
16069  face = (int)rules.GetLSLIntegerItem(idx++);
16070 
16071  if (face == ScriptBaseClass.ALL_SIDES)
16072  {
16073  for (face = 0; face < 21; face++)
16074  {
16076  }
16077  }
16078  else
16079  {
16081  }
16082  break;
16083 
16084  case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
16085  res.Add(new LSL_Integer(0));
16086  res.Add(new LSL_Vector(0f,0f,0f));
16087  res.Add(new LSL_Float(0f)); // intensity
16088  res.Add(new LSL_Float(0f)); // radius
16089  res.Add(new LSL_Float(0f)); // falloff
16090  break;
16091 
16092  case (int)ScriptBaseClass.PRIM_GLOW:
16093  if (remain < 1)
16094  return new LSL_List();
16095  face = (int)rules.GetLSLIntegerItem(idx++);
16096 
16097  if (face == ScriptBaseClass.ALL_SIDES)
16098  {
16099  for (face = 0; face < 21; face++)
16100  {
16101  res.Add(new LSL_Float(0f));
16102  }
16103  }
16104  else
16105  {
16106  res.Add(new LSL_Float(0f));
16107  }
16108  break;
16109 
16110  case (int)ScriptBaseClass.PRIM_TEXT:
16111  res.Add(new LSL_String(""));
16112  res.Add(new LSL_Vector(0f,0f,0f));
16113  res.Add(new LSL_Float(1.0f));
16114  break;
16115 
16116  case (int)ScriptBaseClass.PRIM_NAME:
16117  res.Add(new LSL_String(avatar.Name));
16118  break;
16119 
16120  case (int)ScriptBaseClass.PRIM_DESC:
16121  res.Add(new LSL_String(""));
16122  break;
16123 
16124  case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
16125  Quaternion lrot = avatar.Rotation;
16126  res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
16127  break;
16128 
16129  case (int)ScriptBaseClass.PRIM_POS_LOCAL:
16130  Vector3 lpos = avatar.OffsetPosition;
16131 
16132  if(!avatar.LegacySitOffsets)
16133  {
16134  Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
16135  lpos -= lsitOffset;
16136  }
16137 
16138  res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
16139  break;
16140 
16141  case (int)ScriptBaseClass.PRIM_LINK_TARGET:
16142  if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
16143  return new LSL_List();
16144 
16145  return rules.GetSublist(idx, -1);
16146  }
16147  }
16148 
16149  return new LSL_List();
16150  }
16151 
16152  public void llSetAnimationOverride(LSL_String animState, LSL_String anim)
16153  {
16154  string state = String.Empty;
16155 
16156  foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16157  {
16158  if (kvp.Value.ToLower() == ((string)animState).ToLower())
16159  {
16160  state = kvp.Key;
16161  break;
16162  }
16163  }
16164 
16165  if (state == String.Empty)
16166  {
16167  llShout(ScriptBaseClass.DEBUG_CHANNEL, "Invalid animation state " + animState);
16168  return;
16169  }
16170 
16171  if (m_item.PermsGranter == UUID.Zero)
16172  {
16173  llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16174  return;
16175  }
16176 
16177  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS) == 0)
16178  {
16179  llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16180  return;
16181  }
16182 
16183  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16184 
16185  if (presence == null)
16186  return;
16187 
16188  UUID animID;
16189 
16190  animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
16191 
16192  if (animID == UUID.Zero)
16193  {
16194  String animupper = ((string)anim).ToUpperInvariant();
16195  DefaultAvatarAnimations.AnimsUUID.TryGetValue(animupper, out animID);
16196  }
16197 
16198  if (animID == UUID.Zero)
16199  {
16200  llShout(ScriptBaseClass.DEBUG_CHANNEL, "Animation not found");
16201  return;
16202  }
16203 
16204  presence.SetAnimationOverride(state, animID);
16205  }
16206 
16207  public void llResetAnimationOverride(LSL_String animState)
16208  {
16209  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16210  if (presence == null)
16211  return;
16212 
16213  if (m_item.PermsGranter == UUID.Zero)
16214  {
16215  llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16216  return;
16217  }
16218 
16219  if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS) == 0)
16220  {
16221  llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16222  return;
16223  }
16224 
16225  if (animState == "ALL")
16226  {
16227  presence.SetAnimationOverride("ALL", UUID.Zero);
16228  return;
16229  }
16230 
16231  string state = String.Empty;
16232 
16233  foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16234  {
16235  if (kvp.Value.ToLower() == ((string)animState).ToLower())
16236  {
16237  state = kvp.Key;
16238  break;
16239  }
16240  }
16241 
16242  if (state == String.Empty)
16243  {
16244  return;
16245  }
16246 
16247  presence.SetAnimationOverride(state, UUID.Zero);
16248  }
16249 
16251  {
16252  ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16253  if (presence == null)
16254  return String.Empty;
16255 
16256  if (m_item.PermsGranter == UUID.Zero)
16257  {
16258  llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16259  return String.Empty;
16260  }
16261 
16263  {
16264  llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16265  return String.Empty;
16266  }
16267 
16268  string state = String.Empty;
16269 
16270  foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16271  {
16272  if (kvp.Value.ToLower() == ((string)animState).ToLower())
16273  {
16274  state = kvp.Key;
16275  break;
16276  }
16277  }
16278 
16279  if (state == String.Empty)
16280  {
16281  return String.Empty;
16282  }
16283 
16284  UUID animID = presence.GetAnimationOverride(state);
16285  if (animID == UUID.Zero)
16286  return animState;
16287 
16288  foreach (KeyValuePair<string, UUID> kvp in DefaultAvatarAnimations.AnimsUUID)
16289  {
16290  if (kvp.Value == animID)
16291  return kvp.Key.ToLower();
16292  }
16293 
16294  foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems())
16295  {
16296  if (item.AssetID == animID)
16297  return item.Name;
16298  }
16299 
16300  return String.Empty;
16301  }
16302 
16304  {
16305  OSD o = OSDParser.DeserializeJson(json);
16306  OSD specVal = JsonGetSpecific(o, specifiers, 0);
16307 
16308  return specVal.AsString();
16309  }
16310 
16312  {
16313  try
16314  {
16315  OSD o = OSDParser.DeserializeJson(json);
16316  return (LSL_List)ParseJsonNode(o);
16317  }
16318  catch (Exception)
16319  {
16321  }
16322  }
16323 
16324  private object ParseJsonNode(OSD node)
16325  {
16326  if (node.Type == OSDType.Integer)
16327  return new LSL_Integer(node.AsInteger());
16328  if (node.Type == OSDType.Boolean)
16329  return new LSL_Integer(node.AsBoolean() ? 1 : 0);
16330  if (node.Type == OSDType.Real)
16331  return new LSL_Float(node.AsReal());
16332  if (node.Type == OSDType.UUID || node.Type == OSDType.String)
16333  return new LSL_String(node.AsString());
16334  if (node.Type == OSDType.Array)
16335  {
16336  LSL_List resp = new LSL_List();
16337  OSDArray ar = node as OSDArray;
16338  foreach (OSD o in ar)
16339  resp.Add(ParseJsonNode(o));
16340  return resp;
16341  }
16342  if (node.Type == OSDType.Map)
16343  {
16344  LSL_List resp = new LSL_List();
16345  OSDMap ar = node as OSDMap;
16346  foreach (KeyValuePair<string, OSD> o in ar)
16347  {
16348  resp.Add(new LSL_String(o.Key));
16349  resp.Add(ParseJsonNode(o.Value));
16350  }
16351  return resp;
16352  }
16353  throw new Exception(ScriptBaseClass.JSON_INVALID);
16354  }
16355 
16357  {
16358  try
16359  {
16360  if (type == ScriptBaseClass.JSON_ARRAY)
16361  {
16362  OSDArray array = new OSDArray();
16363  foreach (object o in values.Data)
16364  {
16365  array.Add(ListToJson(o));
16366  }
16367  return OSDParser.SerializeJsonString(array);
16368  }
16369  else if (type == ScriptBaseClass.JSON_OBJECT)
16370  {
16371  OSDMap map = new OSDMap();
16372  for (int i = 0; i < values.Data.Length; i += 2)
16373  {
16374  if (!(values.Data[i] is LSL_String))
16375  return ScriptBaseClass.JSON_INVALID;
16376  map.Add(((LSL_String)values.Data[i]).m_string, ListToJson(values.Data[i + 1]));
16377  }
16378  return OSDParser.SerializeJsonString(map);
16379  }
16380  return ScriptBaseClass.JSON_INVALID;
16381  }
16382  catch (Exception ex)
16383  {
16384  return ex.Message;
16385  }
16386  }
16387 
16388  private OSD ListToJson(object o)
16389  {
16390  if (o is LSL_Float)
16391  return OSD.FromReal(((LSL_Float)o).value);
16392  if (o is LSL_Integer)
16393  {
16394  int i = ((LSL_Integer)o).value;
16395  if (i == 0)
16396  return OSD.FromBoolean(false);
16397  else if (i == 1)
16398  return OSD.FromBoolean(true);
16399  return OSD.FromInteger(i);
16400  }
16401  if (o is LSL_Rotation)
16402  return OSD.FromString(((LSL_Rotation)o).ToString());
16403  if (o is LSL_Vector)
16404  return OSD.FromString(((LSL_Vector)o).ToString());
16405  if (o is LSL_String)
16406  {
16407  string str = ((LSL_String)o).m_string;
16408  if (str == ScriptBaseClass.JSON_NULL)
16409  return new OSD();
16410  return OSD.FromString(str);
16411  }
16412  throw new Exception(ScriptBaseClass.JSON_INVALID);
16413  }
16414 
16415  private OSD JsonGetSpecific(OSD o, LSL_List specifiers, int i)
16416  {
16417  object spec = specifiers.Data[i];
16418  OSD nextVal = null;
16419  if (o is OSDArray)
16420  {
16421  if (spec is LSL_Integer)
16422  nextVal = ((OSDArray)o)[((LSL_Integer)spec).value];
16423  }
16424  if (o is OSDMap)
16425  {
16426  if (spec is LSL_String)
16427  nextVal = ((OSDMap)o)[((LSL_String)spec).m_string];
16428  }
16429  if (nextVal != null)
16430  {
16431  if (specifiers.Data.Length - 1 > i)
16432  return JsonGetSpecific(nextVal, specifiers, i + 1);
16433  }
16434  return nextVal;
16435  }
16436 
16437  public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value)
16438  {
16439  try
16440  {
16441  OSD o = OSDParser.DeserializeJson(json);
16442  JsonSetSpecific(o, specifiers, 0, value);
16443  return OSDParser.SerializeJsonString(o);
16444  }
16445  catch (Exception)
16446  {
16447  }
16448  return ScriptBaseClass.JSON_INVALID;
16449  }
16450 
16451  private void JsonSetSpecific(OSD o, LSL_List specifiers, int i, LSL_String val)
16452  {
16453  object spec = specifiers.Data[i];
16454  // 20131224 not used object specNext = i+1 == specifiers.Data.Length ? null : specifiers.Data[i+1];
16455  OSD nextVal = null;
16456  if (o is OSDArray)
16457  {
16458  OSDArray array = ((OSDArray)o);
16459  if (spec is LSL_Integer)
16460  {
16461  int v = ((LSL_Integer)spec).value;
16462  if (v >= array.Count)
16463  array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
16464  else
16465  nextVal = ((OSDArray)o)[v];
16466  }
16467  else if (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND)
16468  array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
16469  }
16470  if (o is OSDMap)
16471  {
16472  if (spec is LSL_String)
16473  {
16474  OSDMap map = ((OSDMap)o);
16475  if (map.ContainsKey(((LSL_String)spec).m_string))
16476  nextVal = map[((LSL_String)spec).m_string];
16477  else
16478  map.Add(((LSL_String)spec).m_string, JsonBuildRestOfSpec(specifiers, i + 1, val));
16479  }
16480  }
16481  if (nextVal != null)
16482  {
16483  if (specifiers.Data.Length - 1 > i)
16484  {
16485  JsonSetSpecific(nextVal, specifiers, i + 1, val);
16486  return;
16487  }
16488  }
16489  }
16490 
16491  private OSD JsonBuildRestOfSpec(LSL_List specifiers, int i, LSL_String val)
16492  {
16493  object spec = i >= specifiers.Data.Length ? null : specifiers.Data[i];
16494  // 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1];
16495 
16496  if (spec == null)
16497  return OSD.FromString(val);
16498 
16499  if (spec is LSL_Integer ||
16500  (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND))
16501  {
16502  OSDArray array = new OSDArray();
16503  array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
16504  return array;
16505  }
16506  else if (spec is LSL_String)
16507  {
16508  OSDMap map = new OSDMap();
16509  map.Add((LSL_String)spec, JsonBuildRestOfSpec(specifiers, i + 1, val));
16510  return map;
16511  }
16512  return new OSD();
16513  }
16514 
16515  public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers)
16516  {
16517  OSD o = OSDParser.DeserializeJson(json);
16518  OSD specVal = JsonGetSpecific(o, specifiers, 0);
16519  if (specVal == null)
16520  return ScriptBaseClass.JSON_INVALID;
16521  switch (specVal.Type)
16522  {
16523  case OSDType.Array:
16524  return ScriptBaseClass.JSON_ARRAY;
16525  case OSDType.Boolean:
16526  return specVal.AsBoolean() ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE;
16527  case OSDType.Integer:
16528  case OSDType.Real:
16530  case OSDType.Map:
16532  case OSDType.String:
16533  case OSDType.UUID:
16535  case OSDType.Unknown:
16536  return ScriptBaseClass.JSON_NULL;
16537  }
16538  return ScriptBaseClass.JSON_INVALID;
16539  }
16540  }
16541 
16542  public class NotecardCache
16543  {
16544  protected class Notecard
16545  {
16546  public string[] text;
16547  public DateTime lastRef;
16548  }
16549 
16550  private static Dictionary<UUID, Notecard> m_Notecards =
16551  new Dictionary<UUID, Notecard>();
16552 
16553  public static void Cache(UUID assetID, byte[] text)
16554  {
16555  CheckCache();
16556 
16557  lock (m_Notecards)
16558  {
16559  if (m_Notecards.ContainsKey(assetID))
16560  return;
16561 
16562  Notecard nc = new Notecard();
16563  nc.lastRef = DateTime.Now;
16564  try
16565  {
16566  nc.text = SLUtil.ParseNotecardToArray(text);
16567  }
16568  catch(SLUtil.NotANotecardFormatException)
16569  {
16570  nc.text = new string[0];
16571  }
16572  m_Notecards[assetID] = nc;
16573  }
16574  }
16575 
16576  public static bool IsCached(UUID assetID)
16577  {
16578  lock (m_Notecards)
16579  {
16580  return m_Notecards.ContainsKey(assetID);
16581  }
16582  }
16583 
16584  public static int GetLines(UUID assetID)
16585  {
16586  if (!IsCached(assetID))
16587  return -1;
16588 
16589  lock (m_Notecards)
16590  {
16591  m_Notecards[assetID].lastRef = DateTime.Now;
16592  return m_Notecards[assetID].text.Length;
16593  }
16594  }
16595 
16602  public static string GetLine(UUID assetID, int lineNumber)
16603  {
16604  if (lineNumber < 0)
16605  return "";
16606 
16607  string data;
16608 
16609  if (!IsCached(assetID))
16610  return "";
16611 
16612  lock (m_Notecards)
16613  {
16614  m_Notecards[assetID].lastRef = DateTime.Now;
16615 
16616  if (lineNumber >= m_Notecards[assetID].text.Length)
16617  return "\n\n\n";
16618 
16619  data = m_Notecards[assetID].text[lineNumber];
16620 
16621  return data;
16622  }
16623  }
16624 
16637  public static string GetLine(UUID assetID, int lineNumber, int maxLength)
16638  {
16639  string line = GetLine(assetID, lineNumber);
16640 
16641  if (line.Length > maxLength)
16642  line = line.Substring(0, maxLength);
16643 
16644  return line;
16645  }
16646 
16647  public static void CheckCache()
16648  {
16649  lock (m_Notecards)
16650  {
16651  foreach (UUID key in new List<UUID>(m_Notecards.Keys))
16652  {
16653  Notecard nc = m_Notecards[key];
16654  if (nc.lastRef.AddSeconds(30) < DateTime.Now)
16655  m_Notecards.Remove(key);
16656  }
16657  }
16658  }
16659  }
16660 }
int GetNumberOfSides()
Get the number of sides that this part has.
void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
set object position, optionally capping the distance.
Definition: LSL_Api.cs:2671
LSL_Integer llClearPrimMedia(LSL_Integer face)
Definition: LSL_Api.cs:11402
void llGiveInventory(string destination, string inventory)
Definition: LSL_Api.cs:4633
void llShout(int channelID, string text)
Definition: LSL_Api.cs:1232
void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at)
Definition: LSL_Api.cs:7838
LSL_List llGetPrimMediaParams(int face, LSL_List rules)
Definition: LSL_Api.cs:11149
void llGiveInventoryList(string destination, string category, LSL_List inventory)
Definition: LSL_Api.cs:7588
void SetScale(SceneObjectPart part, LSL_Vector scale)
Definition: LSL_Api.cs:1815
LSL_Integer llGiveMoney(string destination, int amount)
Definition: LSL_Api.cs:3396
void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt)
Definition: LSL_Api.cs:12709
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat LSL_Float
Definition: CM_Api.cs:48
LSL_Vector llGroundNormal(LSL_Vector offset)
Definition: LSL_Api.cs:6962
LSL_Vector llRot2Left(LSL_Rotation r)
Definition: LSL_Api.cs:1053
void llOffsetTexture(double u, double v, int face)
Definition: LSL_Api.cs:2451
Quaternion GetWorldRotation()
Gets the rotation of this prim offset by the group rotation
LSL_Integer llGetListLength(LSL_List src)
Definition: LSL_Api.cs:5687
void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
Definition: LSL_Api.cs:1335
LSL_Rotation llGetRot()
See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
Definition: LSL_Api.cs:2810
LSL_String llDumpList2String(LSL_List src, string seperator)
Definition: LSL_Api.cs:7868
void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
Definition: LSL_Api.cs:8498
OpenSim.Region.ScriptEngine.Shared.LSL_Types.list LSL_List
Definition: CM_Api.cs:51
IEntityInventory Inventory
This part's inventory
LSL_Float llList2Float(LSL_List src, int index)
Definition: LSL_Api.cs:5728
void llRegionSay(int channelID, string text)
Definition: LSL_Api.cs:1254
void llSetVehicleFloatParam(int param, LSL_Float value)
Definition: LSL_Api.cs:7655
LSL_Vector llDetectedTouchST(int index)
See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
Definition: LSL_Api.cs:1530
void llSetColor(LSL_Vector color, int face)
Definition: LSL_Api.cs:1860
List< SceneObjectPart > GetLinkParts(int linkType)
Definition: LSL_Api.cs:659
OpenSim.Region.Framework.Scenes.PrimType PrimType
Definition: LSL_Api.cs:66
OpenMetaverse.StructuredData.OSDArray OSDArray
Contains all LSL ll-functions. This class will be in Default AppDomain.
Definition: LSL_Api.cs:95
LSL_Integer llList2Integer(LSL_List src, int index)
Definition: LSL_Api.cs:5694
OpenSim.Framework.Constants.TeleportFlags TeleportFlags
void llTriggerSound(string sound, double volume)
Definition: LSL_Api.cs:3138
Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
void llRequestPermissions(string agent, int perm)
Definition: LSL_Api.cs:4101
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)
Definition: LSL_Api.cs:8211
LSL_Integer llGetInventoryPermMask(string itemName, int mask)
Definition: LSL_Api.cs:11951
int RegionCoordX
The co-ordinate of this region in region units.
void llRemoteLoadScript(string target, string name, int running, int start_param)
Definition: LSL_Api.cs:7968
List< ScenePresence > GetLinkAvatars(int linkType)
Definition: LSL_Api.cs:536
void llGroundRepel(double height, int water, double tau)
Definition: LSL_Api.cs:7563
LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
llListReplaceList removes the sub-list defined by the inclusive indices start and end and inserts the...
Definition: LSL_Api.cs:12212
LSL_Integer llSubStringIndex(string source, string pattern)
Definition: LSL_Api.cs:5638
LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
Elements in the source list starting with 0 and then every i+stride. If the stride is negative then t...
Definition: LSL_Api.cs:6097
void llSensor(string name, string id, int type, double range, double arc)
Definition: LSL_Api.cs:1326
void SetEntityParams(List< ISceneEntity > entities, LSL_List rules, string originFunc)
Definition: LSL_Api.cs:8561
LSL_Key llList2Key(LSL_List src, int index)
Definition: LSL_Api.cs:5798
void ScaleTexture(SceneObjectPart part, double u, double v, int face)
Definition: LSL_Api.cs:2419
bool HasAttachments()
Does this avatar have any attachments?
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString LSL_Key
Definition: CM_Api.cs:50
bool IsTemporary
Is this scene object temporary?
void llWhisper(int channelID, string text)
Definition: LSL_Api.cs:1176
static void Cache(UUID assetID, byte[] text)
Definition: LSL_Api.cs:16553
void llAddToLandBanList(string avatar, double hours)
Definition: LSL_Api.cs:12735
void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
Definition: LSL_Api.cs:3436
OpenSim.Framework.RegionInfo RegionInfo
AccessList Flags
Definition: LandData.cs:41
void llLoopSoundMaster(string sound, double volume)
Definition: LSL_Api.cs:3105
OpenSim.Services.Interfaces.PresenceInfo PresenceInfo
Definition: LSL_Api.cs:65
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger LSL_Integer
Definition: LSL_Api.cs:71
LSL_List llGetAgentList(LSL_Integer scope, LSL_List options)
http://wiki.secondlife.com/wiki/LlGetAgentList The list of options is currently not used in SL scope ...
Definition: LSL_Api.cs:6597
void llSetObjectPermMask(int mask, int value)
Definition: LSL_Api.cs:11915
LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules)
Definition: LSL_Api.cs:11276
LSL_Integer llListen(int channelID, string name, string ID, string msg)
Definition: LSL_Api.cs:1298
void llRotateTexture(double rotation, int face)
Definition: LSL_Api.cs:2490
LSL_List llGetObjectDetails(string id, LSL_List args)
Definition: LSL_Api.cs:13468
LSL_String llInsertString(string dest, int index, string src)
Insert string inserts the specified string identified by src at the index indicated by index...
Definition: LSL_Api.cs:3347
List< LandAccessEntry > ParcelAccessList
List of access data for the parcel. User data, some bitflags, and a time
Definition: LandData.cs:566
LSL_Vector GetColor(SceneObjectPart part, int face)
Definition: LSL_Api.cs:2307
PrimType GetPrimType()
Tell us what type this prim is
void llMoveToTarget(LSL_Vector target, double tau)
Definition: LSL_Api.cs:2952
OpenSim.Framework.PermissionMask PermissionMask
Definition: LSL_Api.cs:80
LSL_Vector GetPartLocalPos(SceneObjectPart part)
Definition: LSL_Api.cs:2709
static string GetLine(UUID assetID, int lineNumber, int maxLength)
Get a notecard line.
Definition: LSL_Api.cs:16637
LSL_String llList2Json(LSL_String type, LSL_List values)
Definition: LSL_Api.cs:16356
bool AttachToAvatar(int attachmentPoint)
Attach the object containing this script to the avatar that owns it.
Definition: LSL_Api.cs:3723
LSL_String llList2String(LSL_List src, int index)
Definition: LSL_Api.cs:5784
PhysicsActor PhysicsActor
Physical scene representation of this Avatar.
LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
Definition: LSL_Api.cs:5510
void llTextBox(string agent, string message, int chatChannel)
Definition: LSL_Api.cs:5073
void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
Definition: LSL_Api.cs:3464
void llAddToLandPassList(string avatar, double hours)
Definition: LSL_Api.cs:7766
LSL_Integer llDetectedTouchFace(int index)
See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
Definition: LSL_Api.cs:1494
float ScriptExecutionTime()
A float the value is a representative execution time in milliseconds of all scripts in the link set...
LSL_String llGetInventoryName(int type, int number)
Definition: LSL_Api.cs:4599
void llSetAngularVelocity(LSL_Vector avel, int local)
Definition: LSL_Api.cs:2922
OpenSim.Services.Interfaces.GridRegion GridRegion
Definition: LSL_Api.cs:64
LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed)
Definition: LSL_Api.cs:10103
LSL_Float llRot2Angle(LSL_Rotation rot)
Definition: LSL_Api.cs:5483
LSL_Integer llDetectedLinkNumber(int number)
Definition: LSL_Api.cs:1469
void llSetPayPrice(int price, LSL_List quick_pay_buttons)
Definition: LSL_Api.cs:12600
void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
Definition: LSL_Api.cs:7899
OpenMetaverse.StructuredData.OSDMap OSDMap
void llSetLinkTexture(int linknumber, string texture, int face)
Definition: LSL_Api.cs:2355
LSL_List llGetBoundingBox(string obj)
Full implementation of llGetBoundingBox according to SL 2015-04-15. http://wiki.secondlife.com/wiki/LlGetBoundingBox http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox Returns local bounding box of avatar without attachments if target is non-seated avatar or prim/mesh in avatar attachment. Returns local bounding box of object including seated avatars if target is seated avatar or prim/mesh in object. Uses meshing of prims for high accuracy or less accurate box models for speed.
Definition: LSL_Api.cs:10484
LSL_Float llCloud(LSL_Vector offset)
Definition: LSL_Api.cs:1588
LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
Definition: LSL_Api.cs:13995
LSL_String llGetEnv(LSL_String name)
Definition: LSL_Api.cs:6202
LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos, bool adjust)
Definition: LSL_Api.cs:2643
List< ISceneEntity > GetLinkEntities(SceneObjectPart part, int linkType)
Definition: LSL_Api.cs:717
LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
Definition: LSL_Api.cs:10711
LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
Definition: LSL_Api.cs:13420
void llCollisionSprite(string impact_sprite)
Definition: LSL_Api.cs:15584
void llSound(string sound, double volume, int queue, int loop)
Definition: LSL_Api.cs:3072
int ScriptCount()
Returns the total count of scripts in all parts inventories.
LSL_List llParcelMediaQuery(LSL_List aList)
Definition: LSL_Api.cs:12538
void llSetVehicleVectorParam(int param, LSL_Vector vec)
Definition: LSL_Api.cs:7667
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
Definition: LSL_Api.cs:3443
bool CheckPermissions(UUID npcID, UUID callerID)
Check if the caller has permission to manipulate the given NPC.
void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate)
Definition: LSL_Api.cs:6715
LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options)
Implementation of llCastRay similar to SL 2015-04-21. http://wiki.secondlife.com/wiki/LlCastRay Uses ...
Definition: LSL_Api.cs:14611
Represents an item in a task inventory
LSL_List llGetParcelPrimOwners(LSL_Vector pos)
Definition: LSL_Api.cs:13374
void llGodLikeRezObject(string inventory, LSL_Vector pos)
Definition: LSL_Api.cs:15591
sbyte Type
(sbyte) AssetType enum
Definition: AssetBase.cs:198
float ScriptExecutionTime()
A float the value is a representative execution time in milliseconds of all scripts in all attachment...
void llScaleTexture(double u, double v, int face)
Definition: LSL_Api.cs:2411
void llMessageLinked(int linknumber, int num, string msg, string id)
Definition: LSL_Api.cs:5159
static string GetLine(UUID assetID, int lineNumber)
Get a notecard line.
Definition: LSL_Api.cs:16602
LSL_Float llGetRegionFPS()
Returns the value reported in the client Statistics window
Definition: LSL_Api.cs:7056
LSL_Vector llRot2Euler(LSL_Rotation q1)
Definition: LSL_Api.cs:872
int RunningScriptCount()
Returns the total count of running scripts in all parts.
void DetachFromAvatar()
Detach the object containing this script from the avatar it is attached to.
Definition: LSL_Api.cs:3742
LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
Definition: LSL_Api.cs:6792
Definition: LandData.cs:37
void llSetLinkAlpha(int linknumber, double alpha, int face)
Definition: LSL_Api.cs:2165
LSL_Vector llList2Vector(LSL_List src, int index)
Definition: LSL_Api.cs:5828
void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
Definition: LSL_Api.cs:3457
LSL_String llGetInventoryKey(string name)
Definition: LSL_Api.cs:5524
void llSetAnimationOverride(LSL_String animState, LSL_String anim)
Definition: LSL_Api.cs:16152
void llLinkParticleSystem(int linknumber, LSL_List rules)
Definition: LSL_Api.cs:7134
LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
Definition: LSL_Api.cs:14030
void llTakeControls(int controls, int accept, int pass_on)
Definition: LSL_Api.cs:3670
Records user information specific to a grid but which is not part of a user's account.
LSL_Integer llScriptDanger(LSL_Vector pos)
Definition: LSL_Api.cs:7884
LSL_Vector llWind(LSL_Vector offset)
Definition: LSL_Api.cs:1605
LSL_String llAvatarOnLinkSitTarget(int linknum)
Definition: LSL_Api.cs:7750
PresenceType
Indicate the type of ScenePresence.
Definition: PresenceType.cs:34
void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
Definition: LSL_Api.cs:3450
void llSetHoverHeight(double height, int water, double tau)
Attempt to clamp the object on the Z axis at the given height over tau seconds.
Definition: LSL_Api.cs:3954
void llSetScriptState(string name, int run)
Definition: LSL_Api.cs:517
LSL_Integer llGetScriptState(string name)
Definition: LSL_Api.cs:498
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString LSL_String
Definition: LSL_Api.cs:75
LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide)
Definition: LSL_Api.cs:13405
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString key
Definition: ICM_Api.cs:31
LSL_String llGetHTTPHeader(LSL_Key request_id, string header)
Definition: LSL_Api.cs:11700
LSL_Rotation llList2Rot(LSL_List src, int index)
Definition: LSL_Api.cs:5861
static List< SceneObjectPart > GetLinkParts(SceneObjectPart part, int linkType)
Definition: LSL_Api.cs:664
void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
Definition: LSL_Api.cs:7709
void llLoadURL(string avatar_id, string message, string url)
Definition: LSL_Api.cs:12285
void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, LSL_Vector bottom_south_west)
Definition: LSL_Api.cs:6755
void SetTexture(SceneObjectPart part, string texture, int face)
Definition: LSL_Api.cs:2372
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3 LSL_Vector
Definition: CM_Api.cs:54
void llSetStatus(int status, int value)
Definition: LSL_Api.cs:1624
void llSetVelocity(LSL_Vector vel, int local)
Definition: LSL_Api.cs:2916
int RegionCoordY
The co-ordinate of this region in region units
LSL_Integer llRotTarget(LSL_Rotation rot, double error)
Definition: LSL_Api.cs:2940
LSL_Integer llListFindList(LSL_List src, LSL_List test)
Returns the index of the first occurrence of test in src.
Definition: LSL_Api.cs:6329
LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
Definition: LSL_Api.cs:13332
bool UsesPhysics
Does this scene object use physics?
void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
Definition: LSL_Api.cs:8454
LSL_Float llAtan2(double x, double y)
Definition: LSL_Api.cs:779
void Initialize(IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
Initialize the API
Definition: LSL_Api.cs:297
LSL_Rotation llDetectedRot(int number)
Definition: LSL_Api.cs:1449
LSL_Vector llRot2Axis(LSL_Rotation rot)
Returns the axis of rotation for a quaternion
Definition: LSL_Api.cs:5461
UUID GlobalID
Global ID for the parcel. (3rd Party Integration)
Definition: LandData.cs:327
bool IsDeleted
Signals whether this entity was in a scene but has since been removed from it.
Definition: EntityBase.cs:73
LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value)
Definition: LSL_Api.cs:16437
Asset class. All Assets are reference by this class or a class derived from this class ...
Definition: AssetBase.cs:49
LSL_Vector llRot2Up(LSL_Rotation r)
Definition: LSL_Api.cs:1078
void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
Definition: LSL_Api.cs:6708
void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
Set a light point on a part
Definition: LSL_Api.cs:2277
void llSetForce(LSL_Vector force, int local)
Definition: LSL_Api.cs:2889
LSL_Integer llGetAgentInfo(string id)
Not fully implemented yet. Still to do:- AGENT_BUSY Remove as they are done
Definition: LSL_Api.cs:6463
LSL_List llListSort(LSL_List src, int stride, int ascending)
Definition: LSL_Api.cs:5676
An interface for a script API module to communicate with the engine it's running under ...
LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers)
Definition: LSL_Api.cs:16303
Keeps track of a specific piece of land's information
Definition: LandObject.cs:43
LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
Definition: LSL_Api.cs:11156
OpenSim.Framework.AssetLandmark AssetLandmark
Definition: LSL_Api.cs:67
void llSetKeyframedMotion(LSL_List frames, LSL_List options)
Definition: LSL_Api.cs:8600
LSL_String llMD5String(string src, int nonce)
Definition: LSL_Api.cs:8091
void llAttachToAvatar(int attachmentPoint)
Definition: LSL_Api.cs:3757
LSL_String llList2CSV(LSL_List src)
Process the supplied list and return the content of the list formatted as a comma separated list...
Definition: LSL_Api.cs:5949
int RegionLocX
The location of this region in meters. DANGER DANGER! Note that this name means something different i...
int PrimCount
Number of prims in this group
void llHTTPResponse(LSL_Key id, int status, string body)
Definition: LSL_Api.cs:13287
LSL_String GetTexture(SceneObjectPart part, int face)
Definition: LSL_Api.cs:2532
LSL_Vector llRot2Fwd(LSL_Rotation r)
Definition: LSL_Api.cs:1028
void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
Definition: LSL_Api.cs:5190
void llParcelMediaCommandList(LSL_List commandList)
Definition: LSL_Api.cs:12297
LSL_String llGetLinkName(int linknum)
Returns the name of the child prim or seated avatar matching the specified link number.
Definition: LSL_Api.cs:4569
LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
Definition: LSL_Api.cs:1102
Vector3 Scale
Change the scale of this part.
void llSetAlpha(double alpha, int face)
Definition: LSL_Api.cs:2158
void llPlaySound(string sound, double volume)
Definition: LSL_Api.cs:3080
LSL_Vector llGroundSlope(LSL_Vector offset)
Definition: LSL_Api.cs:6941
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
Definition: ICM_Api.cs:32
UUID GroupID
Unique ID of the Group that owns
Definition: LandData.cs:342
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat LSL_Float
Definition: LSL_Api.cs:70
LSL_Integer llGetLinkNumberOfSides(int link)
Definition: LSL_Api.cs:5377
LSL_Vector llDetectedTouchUV(int index)
See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
Definition: LSL_Api.cs:1542
LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
Definition: LSL_Api.cs:15723
LSL_Integer llModPow(int a, int b, int c)
Definition: LSL_Api.cs:12579
RegionFlags
Region flags used internally by OpenSimulator to store installation specific information about region...
Definition: RegionFlags.cs:40
LSL_String llTransferLindenDollars(string destination, int amount)
Definition: LSL_Api.cs:15646
void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density)
Definition: LSL_Api.cs:8772
void llSetTorque(LSL_Vector torque, int local)
Definition: LSL_Api.cs:2984
List< TaskInventoryItem > GetInventoryItems()
Get all inventory items.
LSL_List llCSV2List(string src)
The supplied string is scanned for commas and converted into a list. Commas are only effective if the...
Definition: LSL_Api.cs:5968
void llLookAt(LSL_Vector target, double strength, double damping)
Definition: LSL_Api.cs:3548
LSL_String llXorBase64Strings(string str1, string str2)
Definition: LSL_Api.cs:10245
LSL_Integer llSetRegionPos(LSL_Vector pos)
Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki...
Definition: LSL_Api.cs:2582
override Vector3 AbsolutePosition
Position of this avatar relative to the region the avatar is in
LSL_Integer llManageEstateAccess(int action, string avatar)
Definition: LSL_Api.cs:15467
void llResetAnimationOverride(LSL_String animState)
Definition: LSL_Api.cs:16207
void UpdateExtraPhysics(ExtraPhysicsData physdata)
void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
Definition: LSL_Api.cs:7720
LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
Definition: LSL_Api.cs:15895
uint AttachmentPoint
Attachment point of this scene object to an avatar.
LSL_List llDeleteSubList(LSL_List src, int start, int end)
Definition: LSL_Api.cs:5900
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger LSL_Integer
Definition: CM_Api.cs:49
Inventory Item - contains all the properties associated with an individual inventory piece...
LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir)
Definition: LSL_Api.cs:6393
ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum)
Get a given link entity from a linkset (linked objects and any sitting avatars).
Definition: LSL_Api.cs:610
LSL_String llGetSubString(string src, int start, int end)
Return a portion of the designated string bounded by inclusive indices (start and end)...
Definition: LSL_Api.cs:3172
LSL_Vector llDetectedTouchBinormal(int index)
See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
Definition: LSL_Api.cs:1482
OpenSim.Region.OptionalModules.Scripting.Minimodule.Object.SculptType SculptType
Definition: SOPObject.cs:39
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion LSL_Rotation
Definition: CM_Api.cs:52
int RegionLocY
The location of this region in meters. DANGER DANGER! Note that this name means something different i...
LSL_Vector llDetectedTouchNormal(int index)
See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
Definition: LSL_Api.cs:1506
bool IsPhantom
Is this scene object phantom?
LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
Definition: LSL_Api.cs:862
void SetFullBright(SceneObjectPart part, int face, bool bright)
Definition: LSL_Api.cs:2105
Details of a Parcel of land
Definition: LandData.cs:47
void llSetVehicleRotationParam(int param, LSL_Rotation rot)
Definition: LSL_Api.cs:7679
LSL_String llDeleteSubString(string src, int start, int end)
Delete substring removes the specified substring bounded by the inclusive indices start and end...
Definition: LSL_Api.cs:3266
void llTargetOmega(LSL_Vector axis, double spinrate, double gain)
Definition: LSL_Api.cs:4081
void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
Definition: LSL_Api.cs:8507
LSL_Vector llGroundContour(LSL_Vector offset)
Definition: LSL_Api.cs:7012
PhysicsActor PhysActor
The representation of this part in the physics scene.
LSL_Vector GetTextureOffset(SceneObjectPart part, int face)
Definition: LSL_Api.cs:5579
void RotateTexture(SceneObjectPart part, double rotation, int face)
Definition: LSL_Api.cs:2497
void llLinkSitTarget(LSL_Integer link, LSL_Vector offset, LSL_Rotation rot)
Definition: LSL_Api.cs:7726
void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
Definition: LSL_Api.cs:2997
LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
Insert the list identified by src into the list designated by dest such that the first new element ...
Definition: LSL_Api.cs:6274
OpenMetaverse.StructuredData.OSD OSD
LSL_Integer llGetListEntryType(LSL_List src, int index)
Definition: LSL_Api.cs:5905
LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face)
Definition: LSL_Api.cs:11409
bool IsNPC(UUID agentID, Scene scene)
Check if the agent is an NPC.
LSL_String llStringTrim(string src, int type)
Definition: LSL_Api.cs:13459
LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
Definition: LSL_Api.cs:13101
void llLoopSoundSlave(string sound, double volume)
Definition: LSL_Api.cs:3115
LSL_String llGetAnimationOverride(LSL_String animState)
Definition: LSL_Api.cs:16250
Quaternion Rotation
The rotation of the avatar.
Struct for transmitting parameters required for finding llCastRay ray hits.
Definition: LSL_Api.cs:15068
OpenSim.Region.ScriptEngine.Shared.LSL_Types.list LSL_List
Definition: LSL_Api.cs:73
void llListenControl(int number, int active)
Definition: LSL_Api.cs:1310
LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
Definition: LSL_Api.cs:11765
void WithNotecard(UUID assetID, AssetRequestCallback cb)
Definition: LSL_Api.cs:13866
LSL_String llRequestInventoryData(string name)
Definition: LSL_Api.cs:4893
void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot)
Definition: LSL_Api.cs:3469
LSL_Float GetAlpha(SceneObjectPart part, int face)
Definition: LSL_Api.cs:2140
void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
Definition: LSL_Api.cs:3543
int GetNumberOfSides(SceneObjectPart part)
Definition: LSL_Api.cs:5400
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)
Definition: LSL_Api.cs:8316
int ScriptCount()
Returns a count of the number of scripts in this groups parts.
Interactive OpenSim region server
Definition: OpenSim.cs:55
LSL_Float GetTextureRot(SceneObjectPart part, int face)
Definition: LSL_Api.cs:5621
HttpInitialRequestStatus
The initial status of the request before it is placed on the wire.
UUID ID
A UUID containing the ID for the inventory node itself
LSL_String llJsonValueType(LSL_String json, LSL_List specifiers)
Definition: LSL_Api.cs:16515
LSL_String llXorBase64StringsCorrect(string str1, string str2)
Definition: LSL_Api.cs:13037
LSL_String llRequestAgentData(string id, int data)
Definition: LSL_Api.cs:4775
void SetRot(SceneObjectPart part, Quaternion rot)
Definition: LSL_Api.cs:2762
LSL_Float llGround(LSL_Vector offset)
Definition: LSL_Api.cs:1558
void llSetContentType(LSL_Key id, LSL_Integer type)
Definition: LSL_Api.cs:1912
OpenSim.Framework.Animation Animation
void llCollisionSound(string impact_sound, double impact_volume)
Definition: LSL_Api.cs:5113
LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
Definition: LSL_Api.cs:11283
LSL_Rotation llEuler2Rot(LSL_Vector v)
Definition: LSL_Api.cs:946
void llModifyLand(int action, int brush)
Definition: LSL_Api.cs:5103
LSL_List llGetPrimitiveParams(LSL_List rules)
Definition: LSL_Api.cs:10650
LSL_String llGetNotecardLine(string name, int line)
Definition: LSL_Api.cs:13928
int time
Definition: LSL_Api.cs:87
void llRotLookAt(LSL_Rotation target, double strength, double damping)
Definition: LSL_Api.cs:3992
UUID AgentID
Definition: LandData.cs:39
LSL_Integer llGetInventoryType(string name)
Definition: LSL_Api.cs:12588
LSL_Float llPow(double fbase, double fexponent)
Definition: LSL_Api.cs:791
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger LSLInteger
Definition: CM_Constants.cs:31
void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
Definition: LSL_Api.cs:13983
void llLoopSound(string sound, double volume)
Definition: LSL_Api.cs:3095
TaskInventoryItem m_item
Used for script sleeps when we are using co-operative script termination.
Definition: LSL_Api.cs:111
uint ParentID
The parent ID of this part.
UserAccount account
Definition: LSL_Api.cs:88
LSL_Vector llDetectedTouchPos(int index)
See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
Definition: LSL_Api.cs:1518
bool BlockGrabOverride
If true then grabs are blocked no matter what the individual part BlockGrab setting.
void llSetInventoryPermMask(string itemName, int mask, int value)
Definition: LSL_Api.cs:11977
bool IsGroupOwned
Returns true if the Land Parcel is owned by a group
Definition: LandData.cs:357
void llResetScript()
Reset the named script. The script must be present in the same prim.
Definition: LSL_Api.cs:474
void llGetNextEmail(string address, string subject)
Definition: LSL_Api.cs:3898
void llSay(int channelID, string text)
Definition: LSL_Api.cs:1203
List< ISceneEntity > GetLinkEntities(int linkType)
Definition: LSL_Api.cs:712
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString LSL_String
Definition: CM_Api.cs:53
int RunningScriptCount()
Returns a count of the number of running scripts in this groups parts.
Definition: LSL_Api.cs:85
uint Flags
Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags ...
Definition: LandData.cs:402
void llPlaySoundSlave(string sound, double volume)
Definition: LSL_Api.cs:3125
void llSetLinkColor(int linknumber, LSL_Vector color, int face)
Definition: LSL_Api.cs:4285
LSL_String llGetInventoryCreator(string itemName)
Definition: LSL_Api.cs:12012
LSL_List llList2List(LSL_List src, int start, int end)
Definition: LSL_Api.cs:5894
void llApplyImpulse(LSL_Vector force, int local)
Definition: LSL_Api.cs:2964
void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
Definition: LSL_Api.cs:2053
LSL_Rotation llGetRootRotation()
http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation Also tested in sl in regards to the behaviour in attachments/mouselook In the root prim:- Returns the object rotation if not attached Returns the avatars rotation if attached Returns the camera rotation if attached and the avatar is in mouselook
Definition: LSL_Api.cs:10422
void llCreateLink(string target, int parent)
Definition: LSL_Api.cs:4299
void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
Definition: LSL_Api.cs:8066
LSL_Integer llSetMemoryLimit(LSL_Integer limit)
Definition: LSL_Api.cs:15543
LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
Definition: LSL_Api.cs:973
LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
Definition: LSL_Api.cs:8056
LSL_String llRequestSimulatorData(string simulator, int data)
Definition: LSL_Api.cs:12046
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3 LSL_Vector
Definition: LSL_Api.cs:76
void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
Definition: LSL_Api.cs:7981
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString LSL_Key
Definition: LSL_Api.cs:72
Quaternion GetWorldRotation()
Gets the world rotation of this presence.
LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
Definition: LSL_Api.cs:14393
void OffsetTexture(SceneObjectPart part, double u, double v, int face)
Definition: LSL_Api.cs:2458
void SetColor(SceneObjectPart part, LSL_Vector color, int face)
Definition: LSL_Api.cs:1867
void llSetCameraAtOffset(LSL_Vector offset)
Definition: LSL_Api.cs:7829
void llEmail(string address, string subject, string message)
Definition: LSL_Api.cs:3860
void CreateLink(string target, int parent)
Definition: LSL_Api.cs:4318
void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt)
Definition: LSL_Api.cs:5013
LSL_Integer llGetObjectPrimCount(string object_id)
Definition: LSL_Api.cs:13391
void SetGlow(SceneObjectPart part, int face, float glow)
Definition: LSL_Api.cs:2025
LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
Definition: LSL_Api.cs:10671
virtual string Name
The name of this entity
Definition: EntityBase.cs:65
LSL_List llListRandomize(LSL_List src, int stride)
Randomizes the list, be arbitrarily reordering sublists of stride elements. As the stride approaches ...
Definition: LSL_Api.cs:6025
Holds all the data required to execute a scripting event.
Definition: Helpers.cs:281
void llApplyRotationalImpulse(LSL_Vector force, int local)
Definition: LSL_Api.cs:2978
LSL_Integer llGetParcelFlags(LSL_Vector pos)
Definition: LSL_Api.cs:13022
LSL_String llGetNumberOfNotecardLines(string name)
Definition: LSL_Api.cs:13877
void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
Definition: LSL_Api.cs:8267
int LocalID
Internal ID of the parcel. Sometimes the client will try to use this value
Definition: LandData.cs:463
void SetTexGen(SceneObjectPart part, int face, int style)
Definition: LSL_Api.cs:1992
LSL_Float llWater(LSL_Vector offset)
Definition: LSL_Api.cs:4760
void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
Definition: LSL_Api.cs:4087
LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle)
Definition: LSL_Api.cs:5440
void llSetCameraEyeOffset(LSL_Vector offset)
Definition: LSL_Api.cs:7820
void llSetTexture(string texture, int face)
Definition: LSL_Api.cs:2348
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion LSL_Rotation
Definition: LSL_Api.cs:74
void SetAlpha(SceneObjectPart part, double alpha, int face)
Definition: LSL_Api.cs:2181
void llInstantMessage(string user, string message)
Definition: LSL_Api.cs:3801
void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
Definition: LSL_Api.cs:4970
void llRegionSayTo(string target, int channel, string msg)
Definition: LSL_Api.cs:1280
Provides methods from manipulating media-on-a-prim
Definition: IMoapModule.cs:37
SceneObjectPart ParentPart
If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
void llCollisionFilter(string name, string id, int accept)
Definition: LSL_Api.cs:3655
void llSetText(string text, LSL_Vector color, double alpha)
Definition: LSL_Api.cs:4740
PresenceInfo pinfo
Definition: LSL_Api.cs:89
OpenSim.Framework.RegionFlags RegionFlags
Definition: LSL_Api.cs:68
LSL_Float llListStatistics(int operation, LSL_List src)
Definition: LSL_Api.cs:12984
LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
Definition: LSL_Api.cs:8802
void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, float wind, float tension, LSL_Vector Force)
Set flexi parameters of a part.
Definition: LSL_Api.cs:2235
LSL_Vector llGetAgentSize(string id)
According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize only the height of avatars var...
Definition: LSL_Api.cs:6838
Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
Definition: LSL_Api.cs:7110
System.Timers.Timer Timer
Definition: LSL_Api.cs:78
bool IsAttachment
Is this scene object acting as an attachment?
LSL_String llGetLandOwnerAt(LSL_Vector pos)
Definition: LSL_Api.cs:6824
LSL_Integer llTarget(LSL_Vector position, double range)
Definition: LSL_Api.cs:2927
ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
Definition: LSL_Api.cs:8103
uint ParentID
If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero...
UUID OwnerID
Owner Avatar or Group of the parcel. Naturally, all land masses must be owned by someone ...
Definition: LandData.cs:551