From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001
From: onefang
Date: Sun, 19 May 2019 21:24:15 +1000
Subject: Dump OpenSim 0.9.0.1 into it's own branch.
---
.../Api/Implementation/AsyncCommandManager.cs | 123 +-
.../Shared/Api/Implementation/CM_Api.cs | 129 +
.../Shared/Api/Implementation/LSL_Api.cs | 5966 ++++++++++++++------
.../Shared/Api/Implementation/LS_Api.cs | 18 +-
.../Shared/Api/Implementation/MOD_Api.cs | 84 +-
.../Shared/Api/Implementation/OSSL_Api.cs | 2065 +++++--
.../Api/Implementation/Plugins/SensorRepeat.cs | 62 +-
.../Shared/Api/Implementation/Plugins/Timer.cs | 34 +-
.../Api/Implementation/Properties/AssemblyInfo.cs | 10 +-
.../ScriptEngine/Shared/Api/Interface/ICM_Api.cs | 46 +
.../ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 24 +-
.../ScriptEngine/Shared/Api/Interface/IMOD_Api.cs | 2 +-
.../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 50 +-
.../ScriptEngine/Shared/Api/Runtime/CM_Stub.cs | 71 +
.../ScriptEngine/Shared/Api/Runtime/Executor.cs | 2 +
.../Shared/Api/Runtime/LSL_Constants.cs | 79 +-
.../ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | 113 +-
.../ScriptEngine/Shared/Api/Runtime/LS_Stub.cs | 21 +
.../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 173 +-
...nSim.Region.ScriptEngine.Shared.Api.Runtime.mdp | 48 -
.../Shared/Api/Runtime/Properties/AssemblyInfo.cs | 8 +-
.../ScriptEngine/Shared/Api/Runtime/ScriptBase.cs | 2 +
22 files changed, 6572 insertions(+), 2558 deletions(-)
create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp
(limited to 'OpenSim/Region/ScriptEngine/Shared/Api')
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 036cb5d..e01d2e4 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -28,9 +28,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Reflection;
using System.Threading;
-using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
@@ -39,6 +37,8 @@ using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
+using System.Reflection;
+using log4net;
namespace OpenSim.Region.ScriptEngine.Shared.Api
{
@@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
private static Thread cmdHandlerThread;
private static int cmdHandlerThreadCycleSleepms;
-
+ private static int numInstances;
///
/// Lock for reading/writing static components of AsyncCommandManager.
///
@@ -81,64 +81,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public Dataserver DataserverPlugin
{
- get
- {
+ get
+ {
lock (staticLock)
- return m_Dataserver[m_ScriptEngine];
+ return m_Dataserver[m_ScriptEngine];
}
}
public Timer TimerPlugin
{
- get
- {
+ get
+ {
lock (staticLock)
- return m_Timer[m_ScriptEngine];
+ return m_Timer[m_ScriptEngine];
}
}
public HttpRequest HttpRequestPlugin
{
- get
- {
+ get
+ {
lock (staticLock)
- return m_HttpRequest[m_ScriptEngine];
+ return m_HttpRequest[m_ScriptEngine];
}
}
public Listener ListenerPlugin
{
- get
- {
+ get
+ {
lock (staticLock)
- return m_Listener[m_ScriptEngine];
+ return m_Listener[m_ScriptEngine];
}
}
public SensorRepeat SensorRepeatPlugin
{
- get
- {
+ get
+ {
lock (staticLock)
- return m_SensorRepeat[m_ScriptEngine];
+ return m_SensorRepeat[m_ScriptEngine];
}
}
public XmlRequest XmlRequestPlugin
{
- get
- {
+ get
+ {
lock (staticLock)
- return m_XmlRequest[m_ScriptEngine];
+ return m_XmlRequest[m_ScriptEngine];
}
}
public IScriptEngine[] ScriptEngines
{
- get
- {
+ get
+ {
lock (staticLock)
- return m_ScriptEngines.ToArray();
+ return m_ScriptEngines.ToArray();
}
}
@@ -172,18 +172,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!m_XmlRequest.ContainsKey(m_ScriptEngine))
m_XmlRequest[m_ScriptEngine] = new XmlRequest(this);
- StartThread();
- }
- }
-
- private static void StartThread()
- {
- if (cmdHandlerThread == null)
- {
- // Start the thread that will be doing the work
- cmdHandlerThread
- = WorkManager.StartThread(
+ numInstances++;
+ if (cmdHandlerThread == null)
+ {
+ cmdHandlerThread = WorkManager.StartThread(
CmdHandlerThreadLoop, "AsyncLSLCmdHandlerThread", ThreadPriority.Normal, true, true);
+ }
}
}
@@ -194,25 +188,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
cmdHandlerThreadCycleSleepms = 100;
}
+/*
~AsyncCommandManager()
{
// Shut down thread
-// try
-// {
-// if (cmdHandlerThread != null)
-// {
-// if (cmdHandlerThread.IsAlive == true)
-// {
-// cmdHandlerThread.Abort();
-// //cmdHandlerThread.Join();
-// }
-// }
-// }
-// catch
-// {
-// }
- }
+ try
+ {
+ lock (staticLock)
+ {
+ numInstances--;
+ if(numInstances > 0)
+ return;
+ if (cmdHandlerThread != null)
+ {
+ if (cmdHandlerThread.IsAlive == true)
+ {
+ cmdHandlerThread.Abort();
+ //cmdHandlerThread.Join();
+ cmdHandlerThread = null;
+ }
+ }
+ }
+ }
+ catch
+ {
+ }
+ }
+*/
///
/// Main loop for the manager thread
///
@@ -223,11 +226,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
try
{
Thread.Sleep(cmdHandlerThreadCycleSleepms);
-
+ Watchdog.UpdateThread();
DoOneCmdHandlerPass();
-
Watchdog.UpdateThread();
}
+ catch ( System.Threading.ThreadAbortException) { }
catch (Exception e)
{
m_log.Error("[ASYNC COMMAND MANAGER]: Exception in command handler pass: ", e);
@@ -240,24 +243,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
lock (staticLock)
{
// Check HttpRequests
- m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests();
+ try { m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests(); } catch {}
// Check XMLRPCRequests
- m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests();
+ try { m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests(); } catch {}
foreach (IScriptEngine s in m_ScriptEngines)
{
// Check Listeners
- m_Listener[s].CheckListeners();
+ try { m_Listener[s].CheckListeners(); } catch {}
+
// Check timers
- m_Timer[s].CheckTimerEvents();
+ try { m_Timer[s].CheckTimerEvents(); } catch {}
// Check Sensors
- m_SensorRepeat[s].CheckSenseRepeaterEvents();
+ try { m_SensorRepeat[s].CheckSenseRepeaterEvents(); } catch {}
// Check dataserver
- m_Dataserver[s].ExpireRequests();
+ try { m_Dataserver[s].ExpireRequests(); } catch {}
}
}
}
@@ -269,6 +273,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
///
public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID)
{
+ // Remove a specific script
// m_log.DebugFormat("[ASYNC COMMAND MANAGER]: Removing facilities for script {0}", itemID);
lock (staticLock)
@@ -282,7 +287,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Remove from: HttpRequest
IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface();
if (iHttpReq != null)
- iHttpReq.StopHttpRequestsForScript(itemID);
+ iHttpReq.StopHttpRequest(localID, itemID);
IWorldComm comms = engine.World.RequestModuleInterface();
if (comms != null)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
new file mode 100644
index 0000000..3509968
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Threading;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.Remoting.Lifetime;
+using OpenMetaverse;
+using Nini.Config;
+using OpenSim;
+using OpenSim.Framework;
+using OpenSim.Region.CoreModules.World.LightShare;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.ScriptEngine.Shared;
+using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
+using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
+using OpenSim.Region.ScriptEngine.Interfaces;
+using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
+using OpenSim.Services.Interfaces;
+
+using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
+using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
+using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
+using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
+using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
+using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
+using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
+
+namespace OpenSim.Region.ScriptEngine.Shared.Api
+{
+ [Serializable]
+ public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi
+ {
+ internal IScriptEngine m_ScriptEngine;
+ internal SceneObjectPart m_host;
+ internal TaskInventoryItem m_item;
+ internal bool m_CMFunctionsEnabled = false;
+
+ public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
+ {
+ m_ScriptEngine = ScriptEngine;
+ m_host = host;
+ m_item = item;
+
+ if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
+ m_CMFunctionsEnabled = true;
+ }
+
+ public override Object InitializeLifetimeService()
+ {
+ ILease lease = (ILease)base.InitializeLifetimeService();
+
+ if (lease.CurrentState == LeaseState.Initial)
+ {
+ lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
+// lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
+// lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
+ }
+ return lease;
+ }
+
+ public Scene World
+ {
+ get { return m_ScriptEngine.World; }
+ }
+
+ public string cmDetectedCountry(int number)
+ {
+ m_host.AddScriptLPS(1);
+ if(!m_CMFunctionsEnabled)
+ return String.Empty;
+ if(World.UserAccountService == null)
+ return String.Empty;
+ DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
+ if (detectedParams == null)
+ return String.Empty;
+ UUID key = detectedParams.Key;
+ if(key == UUID.Zero)
+ return String.Empty;
+ UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, key);
+ return account.UserCountry;
+ }
+
+ public string cmGetAgentCountry(LSL_Key key)
+ {
+ if(! m_CMFunctionsEnabled)
+ return "";
+ if(World.UserAccountService == null)
+ return String.Empty;
+ if (!World.Permissions.IsGod(m_host.OwnerID))
+ return String.Empty;
+
+ UUID uuid;
+
+ if (!UUID.TryParse(key, out uuid))
+ return String.Empty;
+
+ UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
+ return account.UserCountry;
+ }
+ }
+}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 1399880..bac1468 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,6 +28,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Collections.Specialized;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
@@ -35,10 +36,12 @@ using System.Runtime.Remoting.Lifetime;
using System.Text;
using System.Threading;
using System.Text.RegularExpressions;
+using System.Timers;
using Nini.Config;
using log4net;
using OpenMetaverse;
using OpenMetaverse.Assets;
+using OpenMetaverse.StructuredData; // LitJson is hidden on this
using OpenMetaverse.Packets;
using OpenMetaverse.Rendering;
using OpenSim;
@@ -49,6 +52,7 @@ using OpenSim.Region.CoreModules.World.Land;
using OpenSim.Region.CoreModules.World.Terrain;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Framework.Scenes.Animation;
using OpenSim.Region.Framework.Scenes.Scripting;
using OpenSim.Region.PhysicsModules.SharedBase;
@@ -72,6 +76,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
using System.Reflection;
+using Timer = System.Timers.Timer;
using System.Linq;
using PermissionMask = OpenSim.Framework.PermissionMask;
@@ -98,30 +103,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected SceneObjectPart m_host;
///
- /// Used for script sleeps when we are using co-operative script termination.
- ///
- /// null if co-operative script termination is not active
- ///
/// The item that hosts this script
///
protected TaskInventoryItem m_item;
protected bool throwErrorOnNotImplemented = false;
protected AsyncCommandManager AsyncCommands = null;
+ protected float m_ScriptDelayFactor = 1.0f;
protected float m_ScriptDistanceFactor = 1.0f;
protected float m_MinTimerInterval = 0.5f;
protected float m_recoilScaleFactor = 0.0f;
- protected DateTime m_timer = DateTime.Now;
+ protected double m_timer = Util.GetTimeStampMS();
protected bool m_waitingForScriptAnswer = false;
protected bool m_automaticLinkPermission = false;
protected IMessageTransferModule m_TransferModule = null;
protected int m_notecardLineReadCharsMax = 255;
protected int m_scriptConsoleChannel = 0;
protected bool m_scriptConsoleChannelEnabled = false;
+ protected bool m_debuggerSafe = false;
protected IUrlModule m_UrlModule = null;
+
protected Dictionary m_userInfoCache = new Dictionary();
protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
+ protected int m_sleepMsOnSetTexture = 200;
+ protected int m_sleepMsOnSetLinkTexture = 200;
+ protected int m_sleepMsOnScaleTexture = 200;
+ protected int m_sleepMsOnOffsetTexture = 200;
+ protected int m_sleepMsOnRotateTexture = 200;
+ protected int m_sleepMsOnSetPos = 200;
+ protected int m_sleepMsOnSetRot = 200;
+ protected int m_sleepMsOnSetLocalRot = 200;
+ protected int m_sleepMsOnPreloadSound = 1000;
+ protected int m_sleepMsOnMakeExplosion = 100;
+ protected int m_sleepMsOnMakeFountain = 100;
+ protected int m_sleepMsOnMakeSmoke = 100;
+ protected int m_sleepMsOnMakeFire = 100;
+ protected int m_sleepMsOnRezAtRoot = 100;
+ protected int m_sleepMsOnInstantMessage = 2000;
+ protected int m_sleepMsOnEmail = 20000;
+ protected int m_sleepMsOnCreateLink = 1000;
+ protected int m_sleepMsOnGiveInventory = 3000;
+ protected int m_sleepMsOnRequestAgentData = 100;
+ protected int m_sleepMsOnRequestInventoryData = 1000;
+ protected int m_sleepMsOnSetDamage = 5000;
+ protected int m_sleepMsOnTextBox = 1000;
+ protected int m_sleepMsOnAdjustSoundVolume = 100;
+ protected int m_sleepMsOnEjectFromLand = 5000;
+ protected int m_sleepMsOnAddToLandPassList = 100;
+ protected int m_sleepMsOnDialog = 1000;
+ protected int m_sleepMsOnRemoteLoadScript = 3000;
+ protected int m_sleepMsOnRemoteLoadScriptPin = 3000;
+ protected int m_sleepMsOnOpenRemoteDataChannel = 1000;
+ protected int m_sleepMsOnSendRemoteData = 3000;
+ protected int m_sleepMsOnRemoteDataReply = 3000;
+ protected int m_sleepMsOnCloseRemoteDataChannel = 1000;
+ protected int m_sleepMsOnSetPrimitiveParams = 200;
+ protected int m_sleepMsOnSetLinkPrimitiveParams = 200;
+ protected int m_sleepMsOnXorBase64Strings = 300;
+ protected int m_sleepMsOnSetParcelMusicURL = 2000;
+ protected int m_sleepMsOnGetPrimMediaParams = 1000;
+ protected int m_sleepMsOnGetLinkMedia = 1000;
+ protected int m_sleepMsOnSetPrimMediaParams = 1000;
+ protected int m_sleepMsOnSetLinkMedia = 1000;
+ protected int m_sleepMsOnClearPrimMedia = 1000;
+ protected int m_sleepMsOnClearLinkMedia = 1000;
+ protected int m_sleepMsOnRequestSimulatorData = 1000;
+ protected int m_sleepMsOnLoadURL = 10000;
+ protected int m_sleepMsOnParcelMediaCommandList = 2000;
+ protected int m_sleepMsOnParcelMediaQuery = 2000;
+ protected int m_sleepMsOnModPow = 1000;
+ protected int m_sleepMsOnSetPrimURL = 2000;
+ protected int m_sleepMsOnRefreshPrimURL = 20000;
+ protected int m_sleepMsOnMapDestination = 1000;
+ protected int m_sleepMsOnAddToLandBanList = 100;
+ protected int m_sleepMsOnRemoveFromLandPassList = 100;
+ protected int m_sleepMsOnRemoveFromLandBanList = 100;
+ protected int m_sleepMsOnResetLandBanList = 100;
+ protected int m_sleepMsOnResetLandPassList = 100;
+ protected int m_sleepMsOnGetParcelPrimOwners = 2000;
+ protected int m_sleepMsOnGetNumberOfNotecardLines = 100;
+ protected int m_sleepMsOnGetNotecardLine = 100;
protected string m_internalObjectHost = "lsl.opensim.local";
protected bool m_restrictEmail = false;
protected ISoundModule m_SoundModule = null;
@@ -172,7 +234,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected int m_maxHitsPerPrimInCastRay = 16;
protected int m_maxHitsPerObjectInCastRay = 16;
protected bool m_detectExitsInCastRay = false;
- protected bool m_filterPartsInCastRay = false;
protected bool m_doAttachmentsInCastRay = false;
protected int m_msThrottleInCastRay = 200;
protected int m_msPerRegionInCastRay = 40;
@@ -183,6 +244,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected bool m_useMeshCacheInCastRay = true;
protected static Dictionary m_cachedMeshes = new Dictionary();
+// protected Timer m_ShoutSayTimer;
+ protected int m_SayShoutCount = 0;
+ DateTime m_lastSayShoutCheck;
+
+ private Dictionary MovementAnimationsForLSL =
+ new Dictionary {
+ {"CROUCH", "Crouching"},
+ {"CROUCHWALK", "CrouchWalking"},
+ {"FALLDOWN", "Falling Down"},
+ {"FLY", "Flying"},
+ {"FLYSLOW", "FlyingSlow"},
+ {"HOVER", "Hovering"},
+ {"HOVER_UP", "Hovering Up"},
+ {"HOVER_DOWN", "Hovering Down"},
+ {"JUMP", "Jumping"},
+ {"LAND", "Landing"},
+ {"PREJUMP", "PreJumping"},
+ {"RUN", "Running"},
+ {"SIT","Sitting"},
+ {"SITGROUND","Sitting on Ground"},
+ {"STAND", "Standing"},
+ {"STANDUP", "Standing Up"},
+ {"STRIDE","Striding"},
+ {"SOFT_LAND", "Soft Landing"},
+ {"TURNLEFT", "Turning Left"},
+ {"TURNRIGHT", "Turning Right"},
+ {"WALK", "Walking"}
+ };
+
//An array of HTTP/1.1 headers that are not allowed to be used
//as custom headers by llHTTPRequest.
private string[] HttpStandardHeaders =
@@ -203,9 +293,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void Initialize(
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
{
+ m_lastSayShoutCheck = DateTime.UtcNow;
+
m_ScriptEngine = scriptEngine;
m_host = host;
m_item = item;
+ m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
LoadConfig();
@@ -228,6 +321,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (seConfig != null)
{
+ m_ScriptDelayFactor =
+ seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor);
m_ScriptDistanceFactor =
seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor);
m_MinTimerInterval =
@@ -296,7 +391,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
- m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay);
m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay);
@@ -307,7 +401,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
IConfig smtpConfig = seConfigSource.Configs["SMTP"];
- if (smtpConfig != null)
+ if (smtpConfig != null)
{
// there's an smtp config, so load in the snooze time.
EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
@@ -315,6 +409,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
}
}
+ m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000;
}
public override Object InitializeLifetimeService()
@@ -330,6 +425,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return lease;
}
+ protected SceneObjectPart MonitoringObject()
+ {
+ UUID m = m_host.ParentGroup.MonitoringObject;
+ if (m == UUID.Zero)
+ return null;
+
+ SceneObjectPart p = m_ScriptEngine.World.GetSceneObjectPart(m);
+ if (p == null)
+ m_host.ParentGroup.MonitoringObject = UUID.Zero;
+
+ return p;
+ }
+
+ protected virtual void ScriptSleep(int delay)
+ {
+ delay = (int)((float)delay * m_ScriptDelayFactor);
+ if (delay == 0)
+ return;
+
+ Sleep(delay);
+ }
+
protected virtual void Sleep(int delay)
{
if (m_item == null) // Some unit tests don't set this
@@ -351,6 +468,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
get { return m_ScriptEngine.World; }
}
+ [DebuggerNonUserCode]
public void state(string newState)
{
m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -360,6 +478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// Reset the named script. The script must be present
/// in the same prim.
///
+ [DebuggerNonUserCode]
public void llResetScript()
{
m_host.AddScriptLPS(1);
@@ -376,12 +495,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
UUID item;
- m_host.AddScriptLPS(1);
-
- if ((item = GetScriptByName(name)) != UUID.Zero)
- m_ScriptEngine.ResetScript(item);
- else
+ if ((item = GetScriptByName(name)) == UUID.Zero)
+ {
+ m_host.AddScriptLPS(1);
Error("llResetOtherScript", "Can't find script '" + name + "'");
+ return;
+ }
+ if(item == m_item.ItemID)
+ llResetScript();
+ else
+ {
+ m_host.AddScriptLPS(1);
+ m_ScriptEngine.ResetScript(item);
+ }
}
public LSL_Integer llGetScriptState(string name)
@@ -414,7 +540,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((item = GetScriptByName(name)) != UUID.Zero)
{
- m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
+ m_ScriptEngine.SetScriptState(item, run == 0 ? false : true, item == m_item.ItemID);
}
else
{
@@ -422,6 +548,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
+ public List GetLinkAvatars(int linkType)
+ {
+ List ret = new List();
+ if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
+ return ret;
+
+ // List avs = m_host.ParentGroup.GetLinkedAvatars();
+ // this needs check
+ List avs = m_host.ParentGroup.GetSittingAvatars();
+ switch (linkType)
+ {
+ case ScriptBaseClass.LINK_SET:
+ return avs;
+
+ case ScriptBaseClass.LINK_ROOT:
+ return ret;
+
+ case ScriptBaseClass.LINK_ALL_OTHERS:
+ return avs;
+
+ case ScriptBaseClass.LINK_ALL_CHILDREN:
+ return avs;
+
+ case ScriptBaseClass.LINK_THIS:
+ return ret;
+
+ default:
+ if (linkType < 0)
+ return ret;
+
+ int partCount = m_host.ParentGroup.GetPartCount();
+
+ if (linkType <= partCount)
+ {
+ return ret;
+ }
+ else
+ {
+ linkType = linkType - partCount;
+ if (linkType > avs.Count)
+ {
+ return ret;
+ }
+ else
+ {
+ ret.Add(avs[linkType-1]);
+ return ret;
+ }
+ }
+ }
+ }
+
///
/// Get a given link entity from a linkset (linked objects and any sitting avatars).
///
@@ -501,7 +679,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public static List GetLinkParts(SceneObjectPart part, int linkType)
{
List ret = new List();
- ret.Add(part);
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return ret;
switch (linkType)
{
@@ -509,7 +688,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new List(part.ParentGroup.Parts);
case ScriptBaseClass.LINK_ROOT:
- ret = new List();
ret.Add(part.ParentGroup.RootPart);
return ret;
@@ -529,16 +707,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return ret;
case ScriptBaseClass.LINK_THIS:
+ ret.Add(part);
return ret;
default:
if (linkType < 0)
- return new List();
+ return ret;
SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
if (target == null)
- return new List();
- ret = new List();
+ return ret;
ret.Add(target);
return ret;
}
@@ -648,8 +826,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Float llFrand(double mag)
{
m_host.AddScriptLPS(1);
-
- return Util.RandomClass.NextDouble() * mag;
+ lock (Util.RandomClass)
+ {
+ return Util.RandomClass.NextDouble() * mag;
+ }
}
public LSL_Integer llFloor(double f)
@@ -700,31 +880,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
//Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
- ///
- /// Convert an LSL rotation to a Euler vector.
- ///
- ///
- /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
- /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
- ///
- ///
- ///
- public LSL_Vector llRot2Euler(LSL_Rotation r)
+ // Utility function for llRot2Euler
+
+ public LSL_Vector llRot2Euler(LSL_Rotation q1)
{
m_host.AddScriptLPS(1);
+ LSL_Vector eul = new LSL_Vector();
- LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r.
- double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later.
- if (m == 0.0) return new LSL_Vector();
- double x = Math.Atan2(-v.y, v.z);
- double sin = v.x / m;
- if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
- double y = Math.Asin(sin);
- // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
- v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0)));
- double z = Math.Atan2(v.y, v.x);
-
- return new LSL_Vector(x, y, z);
+ double sqw = q1.s*q1.s;
+ double sqx = q1.x*q1.x;
+ double sqy = q1.z*q1.z;
+ double sqz = q1.y*q1.y;
+ double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
+ double test = q1.x*q1.z + q1.y*q1.s;
+ if (test > 0.4999*unit) { // singularity at north pole
+ eul.z = 2 * Math.Atan2(q1.x,q1.s);
+ eul.y = Math.PI/2;
+ eul.x = 0;
+ return eul;
+ }
+ if (test < -0.4999*unit) { // singularity at south pole
+ eul.z = -2 * Math.Atan2(q1.x,q1.s);
+ eul.y = -Math.PI/2;
+ eul.x = 0;
+ return eul;
+ }
+ eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
+ eul.y = Math.Asin(2*test/unit);
+ eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
+ return eul;
}
/* From wiki:
@@ -777,18 +961,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
double x,y,z,s;
-
- double c1 = Math.Cos(v.x * 0.5);
- double c2 = Math.Cos(v.y * 0.5);
- double c3 = Math.Cos(v.z * 0.5);
- double s1 = Math.Sin(v.x * 0.5);
- double s2 = Math.Sin(v.y * 0.5);
- double s3 = Math.Sin(v.z * 0.5);
-
- x = s1 * c2 * c3 + c1 * s2 * s3;
- y = c1 * s2 * c3 - s1 * c2 * s3;
- z = s1 * s2 * c3 + c1 * c2 * s3;
- s = c1 * c2 * c3 - s1 * s2 * s3;
+ v.x *= 0.5;
+ v.y *= 0.5;
+ v.z *= 0.5;
+ double c1 = Math.Cos(v.x);
+ double c2 = Math.Cos(v.y);
+ double c1c2 = c1 * c2;
+ double s1 = Math.Sin(v.x);
+ double s2 = Math.Sin(v.y);
+ double s1s2 = s1 * s2;
+ double c1s2 = c1 * s2;
+ double s1c2 = s1 * c2;
+ double c3 = Math.Cos(v.z);
+ double s3 = Math.Sin(v.z);
+
+ x = s1c2 * c3 + c1s2 * s3;
+ y = c1s2 * c3 - s1c2 * s3;
+ z = s1s2 * c3 + c1c2 * s3;
+ s = c1c2 * c3 - s1s2 * s3;
return new LSL_Rotation(x, y, z, s);
}
@@ -926,75 +1116,74 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
//A and B should both be normalized
m_host.AddScriptLPS(1);
- LSL_Rotation rotBetween;
- // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
- // continue calculation.
- if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
+ /* This method is more accurate than the SL one, and thus causes problems
+ for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
+
+ double dotProduct = LSL_Vector.Dot(a, b);
+ LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
+ double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
+ double angle = Math.Acos(dotProduct / magProduct);
+ LSL_Vector axis = LSL_Vector.Norm(crossProduct);
+ double s = Math.Sin(angle / 2);
+
+ double x = axis.x * s;
+ double y = axis.y * s;
+ double z = axis.z * s;
+ double w = Math.Cos(angle / 2);
+
+ if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
+ return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
+
+ return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
+ */
+
+ // This method mimics the 180 errors found in SL
+ // See www.euclideanspace.com... angleBetween
+ LSL_Vector vec_a = a;
+ LSL_Vector vec_b = b;
+
+ // Eliminate zero length
+ LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
+ LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
+ if (vec_a_mag < 0.00001 ||
+ vec_b_mag < 0.00001)
{
- rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
+ return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
}
- else
+
+ // Normalize
+ vec_a = llVecNorm(vec_a);
+ vec_b = llVecNorm(vec_b);
+
+ // Calculate axis and rotation angle
+ LSL_Vector axis = vec_a % vec_b;
+ LSL_Float cos_theta = vec_a * vec_b;
+
+ // Check if parallel
+ if (cos_theta > 0.99999)
{
- a = LSL_Vector.Norm(a);
- b = LSL_Vector.Norm(b);
- double dotProduct = LSL_Vector.Dot(a, b);
- // There are two degenerate cases possible. These are for vectors 180 or
- // 0 degrees apart. These have to be detected and handled individually.
- //
- // Check for vectors 180 degrees apart.
- // A dot product of -1 would mean the angle between vectors is 180 degrees.
- if (dotProduct < -0.9999999f)
- {
- // First assume X axis is orthogonal to the vectors.
- LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
- orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
- // Check for near zero vector. A very small non-zero number here will create
- // a rotation in an undesired direction.
- if (LSL_Vector.Mag(orthoVector) > 0.0001)
- {
- rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f);
- }
- // If the magnitude of the vector was near zero, then assume the X axis is not
- // orthogonal and use the Z axis instead.
- else
- {
- // Set 180 z rotation.
- rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
- }
- }
- // Check for parallel vectors.
- // A dot product of 1 would mean the angle between vectors is 0 degrees.
- else if (dotProduct > 0.9999999f)
- {
- // Set zero rotation.
- rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- // All special checks have been performed so get the axis of rotation.
- LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
- // Quarternion s value is the length of the unit vector + dot product.
- double qs = 1.0 + dotProduct;
- rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
- // Normalize the rotation.
- double mag = LSL_Rotation.Mag(rotBetween);
- // We shouldn't have to worry about a divide by zero here. The qs value will be
- // non-zero because we already know if we're here, then the dotProduct is not -1 so
- // qs will not be zero. Also, we've already handled the input vectors being zero so the
- // crossProduct vector should also not be zero.
- rotBetween.x = rotBetween.x / mag;
- rotBetween.y = rotBetween.y / mag;
- rotBetween.z = rotBetween.z / mag;
- rotBetween.s = rotBetween.s / mag;
- // Check for undefined values and set zero rotation if any found. This code might not actually be required
- // any longer since zero vectors are checked for at the top.
- if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
- {
- rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
- }
- }
+ return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ // Check if anti-parallel
+ else if (cos_theta < -0.99999)
+ {
+ LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
+ if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
+ return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
+ }
+ else // other rotation
+ {
+ LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
+ axis = llVecNorm(axis);
+ double x, y, z, s, t;
+ s = Math.Cos(theta);
+ t = Math.Sin(theta);
+ x = axis.x * t;
+ y = axis.y * t;
+ z = axis.z * t;
+ return new LSL_Rotation(x,y,z,s);
}
- return rotBetween;
}
public void llWhisper(int channelID, string text)
@@ -1012,10 +1201,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
}
+ private void CheckSayShoutTime()
+ {
+ DateTime now = DateTime.UtcNow;
+ if ((now - m_lastSayShoutCheck).Ticks > 10000000) // 1sec
+ {
+ m_lastSayShoutCheck = now;
+ m_SayShoutCount = 0;
+ }
+ else
+ m_SayShoutCount++;
+ }
+
public void llSay(int channelID, string text)
{
m_host.AddScriptLPS(1);
+ if (channelID == 0)
+// m_SayShoutCount++;
+ CheckSayShoutTime();
+
+ if (m_SayShoutCount >= 11)
+ ScriptSleep(2000);
+
if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
{
Console.WriteLine(text);
@@ -1038,6 +1246,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
+ if (channelID == 0)
+// m_SayShoutCount++;
+ CheckSayShoutTime();
+
+ if (m_SayShoutCount >= 11)
+ ScriptSleep(2000);
+
if (text.Length > 1023)
text = text.Substring(0, 1023);
@@ -1062,8 +1277,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
- World.SimChat(Utils.StringToBytes(text),
- ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
+ // debug channel is also sent to avatars
+ if (channelID == ScriptBaseClass.DEBUG_CHANNEL)
+ {
+ World.SimChat(Utils.StringToBytes(text),
+ ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
+
+ }
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
if (wComm != null)
@@ -1078,16 +1298,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
if (channel == ScriptBaseClass.DEBUG_CHANNEL)
- {
return;
- }
UUID TargetID;
UUID.TryParse(target, out TargetID);
- World.SimChatToAgent(TargetID, Utils.StringToBytes(msg),
- channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
-
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface();
if (wComm != null)
wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg);
@@ -1346,10 +1561,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return detectedParams.TouchUV;
}
+ [DebuggerNonUserCode]
public virtual void llDie()
{
m_host.AddScriptLPS(1);
- throw new SelfDeleteException();
+ if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
}
public LSL_Float llGround(LSL_Vector offset)
@@ -1420,6 +1636,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llSetStatus(int status, int value)
{
+ if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
+ return;
m_host.AddScriptLPS(1);
int statusrotationaxis = 0;
@@ -1431,18 +1649,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SceneObjectGroup group = m_host.ParentGroup;
bool allow = true;
+ int maxprims = World.m_linksetPhysCapacity;
+ bool checkShape = (maxprims > 0 && group.PrimCount > maxprims);
+
foreach (SceneObjectPart part in group.Parts)
{
+ if (part.PhysicsShapeType == (byte)PhysicsShapeType.None)
+ continue;
+
if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
{
allow = false;
break;
}
+ if (checkShape)
+ {
+ if (--maxprims < 0)
+ {
+ allow = false;
+ break;
+ }
+ }
}
if (!allow)
return;
+ if (m_host.ParentGroup.RootPart.PhysActor != null &&
+ m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
+ return;
+
m_host.ScriptSetPhysicsStatus(true);
}
else
@@ -1586,6 +1822,53 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return 0;
}
+ public LSL_Integer llScaleByFactor(double scaling_factor)
+ {
+ m_host.AddScriptLPS(1);
+ SceneObjectGroup group = m_host.ParentGroup;
+
+ if(scaling_factor < 1e-6)
+ return ScriptBaseClass.FALSE;
+ if(scaling_factor > 1e6)
+ return ScriptBaseClass.FALSE;
+
+ if (group == null || group.IsDeleted || group.inTransit)
+ return ScriptBaseClass.FALSE;
+
+ if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
+ return ScriptBaseClass.FALSE;
+
+ if (group.RootPart.KeyframeMotion != null)
+ return ScriptBaseClass.FALSE;
+
+ if(group.GroupResize(scaling_factor))
+ return ScriptBaseClass.TRUE;
+ else
+ return ScriptBaseClass.FALSE;
+ }
+
+ public LSL_Float llGetMaxScaleFactor()
+ {
+ m_host.AddScriptLPS(1);
+ SceneObjectGroup group = m_host.ParentGroup;
+
+ if (group == null || group.IsDeleted || group.inTransit)
+ return 1.0f;
+
+ return (LSL_Float)group.GetMaxGroupResizeScale();
+ }
+
+ public LSL_Float llGetMinScaleFactor()
+ {
+ m_host.AddScriptLPS(1);
+ SceneObjectGroup group = m_host.ParentGroup;
+
+ if (group == null || group.IsDeleted || group.inTransit)
+ return 1.0f;
+
+ return (LSL_Float)group.GetMinGroupResizeScale();
+ }
+
public void llSetScale(LSL_Vector scale)
{
m_host.AddScriptLPS(1);
@@ -1641,6 +1924,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
+ SetColor(m_host, color, face);
+ }
+
+ protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
+ {
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
+ Primitive.TextureEntry tex = part.Shape.Textures;
+ int nsides = GetNumberOfSides(part);
+ Color4 texcolor;
+
+ if (face >= 0 && face < nsides)
+ {
+ texcolor = tex.CreateFace((uint)face).RGBA;
+ texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
+ texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
+ texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
+ tex.FaceTextures[face].RGBA = texcolor;
+ part.UpdateTextureEntry(tex.GetBytes());
+ return;
+ }
+ else if (face == ScriptBaseClass.ALL_SIDES)
+ {
+ for (uint i = 0; i < nsides; i++)
+ {
+ if (tex.FaceTextures[i] != null)
+ {
+ texcolor = tex.FaceTextures[i].RGBA;
+ texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
+ texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
+ texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
+ tex.FaceTextures[i].RGBA = texcolor;
+ }
+ texcolor = tex.DefaultTexture.RGBA;
+ texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
+ texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
+ texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
+ tex.DefaultTexture.RGBA = texcolor;
+ }
+ part.UpdateTextureEntry(tex.GetBytes());
+ return;
+ }
+
if (face == ScriptBaseClass.ALL_SIDES)
face = SceneObjectPart.ALL_SIDES;
@@ -1714,15 +2041,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
+/*
+ public void llSetContentType(LSL_Key id, LSL_Integer content_type)
+ {
+ if (m_UrlModule != null)
+ {
+ string type = "text.plain";
+ if (content_type == (int)ScriptBaseClass.CONTENT_TYPE_HTML)
+ type = "text/html";
+
+ m_UrlModule.HttpContentType(new UUID(id),type);
+ }
+ }
+*/
public void SetTexGen(SceneObjectPart part, int face,int style)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
Primitive.TextureEntry tex = part.Shape.Textures;
MappingType textype;
textype = MappingType.Default;
if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR)
textype = MappingType.Planar;
- if (face >= 0 && face < GetNumberOfSides(part))
+ int nsides = GetNumberOfSides(part);
+
+ if (face >= 0 && face < nsides)
{
tex.CreateFace((uint) face);
tex.FaceTextures[face].TexMapType = textype;
@@ -1731,7 +2076,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else if (face == ScriptBaseClass.ALL_SIDES)
{
- for (uint i = 0; i < GetNumberOfSides(part); i++)
+ for (uint i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -1746,8 +2091,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void SetGlow(SceneObjectPart part, int face, float glow)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
Primitive.TextureEntry tex = part.Shape.Textures;
- if (face >= 0 && face < GetNumberOfSides(part))
+ int nsides = GetNumberOfSides(part);
+
+ if (face >= 0 && face < nsides)
{
tex.CreateFace((uint) face);
tex.FaceTextures[face].Glow = glow;
@@ -1756,7 +2106,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else if (face == ScriptBaseClass.ALL_SIDES)
{
- for (uint i = 0; i < GetNumberOfSides(part); i++)
+ for (uint i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -1771,6 +2121,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
Shininess sval = new Shininess();
@@ -1793,8 +2145,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break;
}
+ int nsides = GetNumberOfSides(part);
+
Primitive.TextureEntry tex = part.Shape.Textures;
- if (face >= 0 && face < GetNumberOfSides(part))
+ if (face >= 0 && face < nsides)
{
tex.CreateFace((uint) face);
tex.FaceTextures[face].Shiny = sval;
@@ -1804,7 +2158,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else if (face == ScriptBaseClass.ALL_SIDES)
{
- for (uint i = 0; i < GetNumberOfSides(part); i++)
+ for (uint i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -1821,8 +2175,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void SetFullBright(SceneObjectPart part, int face, bool bright)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
+ int nsides = GetNumberOfSides(part);
Primitive.TextureEntry tex = part.Shape.Textures;
- if (face >= 0 && face < GetNumberOfSides(part))
+ if (face >= 0 && face < nsides)
{
tex.CreateFace((uint) face);
tex.FaceTextures[face].Fullbright = bright;
@@ -1831,7 +2189,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else if (face == ScriptBaseClass.ALL_SIDES)
{
- for (uint i = 0; i < GetNumberOfSides(part); i++)
+ for (uint i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -1854,15 +2212,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected LSL_Float GetAlpha(SceneObjectPart part, int face)
{
Primitive.TextureEntry tex = part.Shape.Textures;
+ int nsides = GetNumberOfSides(part);
if (face == ScriptBaseClass.ALL_SIDES)
{
int i;
double sum = 0.0;
- for (i = 0 ; i < GetNumberOfSides(part); i++)
+ for (i = 0 ; i < nsides; i++)
sum += (double)tex.GetFace((uint)i).RGBA.A;
return sum;
}
- if (face >= 0 && face < GetNumberOfSides(part))
+ if (face >= 0 && face < nsides)
{
return (double)tex.GetFace((uint)face).RGBA.A;
}
@@ -1881,16 +2240,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
List parts = GetLinkParts(linknumber);
-
- foreach (SceneObjectPart part in parts)
- SetAlpha(part, alpha, face);
+ if (parts.Count > 0)
+ {
+ try
+ {
+ foreach (SceneObjectPart part in parts)
+ SetAlpha(part, alpha, face);
+ }
+ finally { }
+ }
}
protected void SetAlpha(SceneObjectPart part, double alpha, int face)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
Primitive.TextureEntry tex = part.Shape.Textures;
+ int nsides = GetNumberOfSides(part);
Color4 texcolor;
- if (face >= 0 && face < GetNumberOfSides(part))
+
+ if (face >= 0 && face < nsides)
{
texcolor = tex.CreateFace((uint)face).RGBA;
texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
@@ -1900,7 +2270,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else if (face == ScriptBaseClass.ALL_SIDES)
{
- for (int i = 0; i < GetNumberOfSides(part); i++)
+ for (int i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -1940,7 +2310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
float wind, float tension, LSL_Vector Force)
{
- if (part == null)
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
if (flexi)
@@ -1981,7 +2351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
///
protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
{
- if (part == null)
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
if (light)
@@ -2014,11 +2384,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
Primitive.TextureEntry tex = part.Shape.Textures;
Color4 texcolor;
LSL_Vector rgb = new LSL_Vector();
+ int nsides = GetNumberOfSides(part);
+
if (face == ScriptBaseClass.ALL_SIDES)
{
int i;
-
- for (i = 0 ; i < GetNumberOfSides(part); i++)
+ for (i = 0; i < nsides; i++)
{
texcolor = tex.GetFace((uint)i).RGBA;
rgb.x += texcolor.R;
@@ -2026,14 +2397,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
rgb.z += texcolor.B;
}
- rgb.x /= (float)GetNumberOfSides(part);
- rgb.y /= (float)GetNumberOfSides(part);
- rgb.z /= (float)GetNumberOfSides(part);
+ float invnsides = 1.0f / (float)nsides;
+
+ rgb.x *= invnsides;
+ rgb.y *= invnsides;
+ rgb.z *= invnsides;
return rgb;
}
-
- if (face >= 0 && face < GetNumberOfSides(part))
+ if (face >= 0 && face < nsides)
{
texcolor = tex.GetFace((uint)face).RGBA;
rgb.x = texcolor.R;
@@ -2052,6 +2424,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
SetTexture(m_host, texture, face);
+ ScriptSleep(m_sleepMsOnSetTexture);
}
public void llSetLinkTexture(int linknumber, string texture, int face)
@@ -2059,13 +2432,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
List parts = GetLinkParts(linknumber);
-
- foreach (SceneObjectPart part in parts)
- SetTexture(part, texture, face);
+ if (parts.Count > 0)
+ {
+ try
+ {
+ foreach (SceneObjectPart part in parts)
+ SetTexture(part, texture, face);
+ }
+ finally { }
+ }
+ ScriptSleep(m_sleepMsOnSetLinkTexture);
}
protected void SetTexture(SceneObjectPart part, string texture, int face)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
UUID textureID = new UUID();
textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
@@ -2075,9 +2458,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
}
+
Primitive.TextureEntry tex = part.Shape.Textures;
+ int nsides = GetNumberOfSides(part);
- if (face >= 0 && face < GetNumberOfSides(part))
+ if (face >= 0 && face < nsides)
{
Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
texface.TextureID = textureID;
@@ -2087,7 +2472,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else if (face == ScriptBaseClass.ALL_SIDES)
{
- for (uint i = 0; i < GetNumberOfSides(part); i++)
+ for (uint i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -2105,12 +2490,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
ScaleTexture(m_host, u, v, face);
+ ScriptSleep(m_sleepMsOnScaleTexture);
}
protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
Primitive.TextureEntry tex = part.Shape.Textures;
- if (face >= 0 && face < GetNumberOfSides(part))
+ int nsides = GetNumberOfSides(part);
+
+ if (face >= 0 && face < nsides)
{
Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
texface.RepeatU = (float)u;
@@ -2121,7 +2512,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
if (face == ScriptBaseClass.ALL_SIDES)
{
- for (int i = 0; i < GetNumberOfSides(part); i++)
+ for (int i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -2140,12 +2531,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
OffsetTexture(m_host, u, v, face);
+ ScriptSleep(m_sleepMsOnOffsetTexture);
}
protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
Primitive.TextureEntry tex = part.Shape.Textures;
- if (face >= 0 && face < GetNumberOfSides(part))
+ int nsides = GetNumberOfSides(part);
+
+ if (face >= 0 && face < nsides)
{
Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
texface.OffsetU = (float)u;
@@ -2156,7 +2553,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
if (face == ScriptBaseClass.ALL_SIDES)
{
- for (int i = 0; i < GetNumberOfSides(part); i++)
+ for (int i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -2175,12 +2572,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
RotateTexture(m_host, rotation, face);
+ ScriptSleep(m_sleepMsOnRotateTexture);
}
protected void RotateTexture(SceneObjectPart part, double rotation, int face)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
Primitive.TextureEntry tex = part.Shape.Textures;
- if (face >= 0 && face < GetNumberOfSides(part))
+ int nsides = GetNumberOfSides(part);
+
+ if (face >= 0 && face < nsides)
{
Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
texface.Rotation = (float)rotation;
@@ -2190,7 +2593,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
if (face == ScriptBaseClass.ALL_SIDES)
{
- for (int i = 0; i < GetNumberOfSides(part); i++)
+ for (int i = 0; i < nsides; i++)
{
if (tex.FaceTextures[i] != null)
{
@@ -2212,12 +2615,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected LSL_String GetTexture(SceneObjectPart part, int face)
{
Primitive.TextureEntry tex = part.Shape.Textures;
+ int nsides = GetNumberOfSides(part);
+
if (face == ScriptBaseClass.ALL_SIDES)
{
face = 0;
}
- if (face >= 0 && face < GetNumberOfSides(part))
+ if (face >= 0 && face < nsides)
{
Primitive.TextureEntryFace texface;
texface = tex.GetFace((uint)face);
@@ -2248,6 +2653,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
SetPos(m_host, pos, true);
+
+ ScriptSleep(m_sleepMsOnSetPos);
}
///
@@ -2278,7 +2685,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
- pos.y > (World.RegionInfo.RegionSizeY + 10) // return FALSE if more than 10 meters into a north-adjacent region.
+ pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
+ pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
)
)
{
@@ -2317,7 +2725,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return end;
}
- protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos)
+ protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos, bool adjust)
{
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return fromPos;
@@ -2333,9 +2741,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
targetPos.z = ground;
}
- LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos);
+ if (adjust)
+ return SetPosAdjust(fromPos, targetPos);
- return real_vec;
+ return targetPos;
}
///
@@ -2346,27 +2755,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// if TRUE, will cap the distance to 10m.
protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
{
- // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted || part.ParentGroup.inTransit)
+ return;
+
+
LSL_Vector currentPos = GetPartLocalPos(part);
+ LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos, adjust);
- float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
- bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
if (part.ParentGroup.RootPart == part)
{
- if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
- targetPos.z = ground;
SceneObjectGroup parent = part.ParentGroup;
- parent.UpdateGroupPosition(!adjust ? targetPos :
- SetPosAdjust(currentPos, targetPos));
+ if (!parent.IsAttachment && !World.Permissions.CanObjectEntry(parent, false, (Vector3)toPos))
+ return;
+ parent.UpdateGroupPosition((Vector3)toPos);
}
else
{
- part.OffsetPosition = !adjust ? targetPos :
- SetPosAdjust(currentPos, targetPos);
- SceneObjectGroup parent = part.ParentGroup;
- parent.HasGroupChanged = true;
- parent.ScheduleGroupForTerseUpdate();
+ part.OffsetPosition = (Vector3)toPos;
+// SceneObjectGroup parent = part.ParentGroup;
+// parent.HasGroupChanged = true;
+// parent.ScheduleGroupForTerseUpdate();
+ part.ScheduleTerseUpdate();
}
}
@@ -2395,13 +2805,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
else
{
if (part.ParentGroup.IsAttachment)
- {
pos = part.AttachedPos;
- }
else
- {
pos = part.AbsolutePosition;
- }
}
// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
@@ -2414,7 +2820,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
// try to let this work as in SL...
- if (m_host.ParentID == 0)
+ if (m_host.ParentID == 0 || (m_host.ParentGroup != null && m_host == m_host.ParentGroup.RootPart))
{
// special case: If we are root, rotate complete SOG to new rotation
SetRot(m_host, rot);
@@ -2428,35 +2834,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
}
}
+
+ ScriptSleep(m_sleepMsOnSetRot);
}
public void llSetLocalRot(LSL_Rotation rot)
{
m_host.AddScriptLPS(1);
SetRot(m_host, rot);
+ ScriptSleep(m_sleepMsOnSetLocalRot);
}
protected void SetRot(SceneObjectPart part, Quaternion rot)
{
- part.UpdateRotation(rot);
- // Update rotation does not move the object in the physics scene if it's a linkset.
-
-//KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type
-// part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
-
- // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
- // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
- // It's perfectly okay when the object is not an active physical body though.
- // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
- // but only if the object is not physial and active. This is important for rotating doors.
- // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
- // scene
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
+ bool isroot = (part == part.ParentGroup.RootPart);
+ bool isphys;
+
PhysicsActor pa = part.PhysActor;
- if (pa != null && !pa.IsPhysical)
+ // keep using physactor ideia of isphysical
+ // it should be SOP ideia of that
+ // not much of a issue with ubOde
+ if (pa != null && pa.IsPhysical)
+ isphys = true;
+ else
+ isphys = false;
+
+ // SL doesn't let scripts rotate root of physical linksets
+ if (isroot && isphys)
+ return;
+
+ part.UpdateRotation(rot);
+
+ // Update rotation does not move the object in the physics engine if it's a non physical linkset
+ // so do a nasty update of parts positions if is a root part rotation
+ if (isroot && pa != null) // with if above implies non physical root part
{
part.ParentGroup.ResetChildPrimPhysicsPositions();
}
+ else // fix sitting avatars. This is only needed bc of how we link avas to child parts, not root part
+ {
+ // List sittingavas = part.ParentGroup.GetLinkedAvatars();
+ List sittingavas = part.ParentGroup.GetSittingAvatars();
+ if (sittingavas.Count > 0)
+ {
+ foreach (ScenePresence av in sittingavas)
+ {
+ if (isroot || part.LocalId == av.ParentID)
+ av.SendTerseUpdateToAllClients();
+ }
+ }
+ }
}
///
@@ -2473,6 +2904,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
Quaternion q = m_host.GetWorldRotation();
+
+ if (m_host.ParentGroup != null && m_host.ParentGroup.AttachmentPoint != 0)
+ {
+ ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
+ if (avatar != null)
+ {
+ if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
+ q = avatar.CameraRotation * q; // Mouselook
+ else
+ q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
+ }
+ }
+
return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
}
@@ -2500,14 +2944,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_Rotation(q);
}
- return new LSL_Rotation(part.GetWorldRotation());
+ q = part.GetWorldRotation();
+ if (part.ParentGroup.AttachmentPoint != 0)
+ {
+ ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
+ if (avatar != null)
+ {
+ if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
+ q = avatar.CameraRotation * q; // Mouselook
+ else
+ q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
+ }
+ }
+
+ return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
}
public LSL_Rotation llGetLocalRot()
{
- m_host.AddScriptLPS(1);
+ return GetPartLocalRot(m_host);
+ }
- return new LSL_Rotation(m_host.RotationOffset);
+ private LSL_Rotation GetPartLocalRot(SceneObjectPart part)
+ {
+ m_host.AddScriptLPS(1);
+ Quaternion rot = part.RotationOffset;
+ return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
}
public void llSetForce(LSL_Vector force, int local)
@@ -2537,32 +2999,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return force;
}
- public void llSetVelocity(LSL_Vector velocity, int local)
+ public void llSetVelocity(LSL_Vector vel, int local)
{
m_host.AddScriptLPS(1);
-
- if (!m_host.ParentGroup.IsDeleted)
- {
- if (local != 0)
- velocity *= llGetRot();
-
- m_host.ParentGroup.RootPart.Velocity = velocity;
- }
+ m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0);
}
- public void llSetAngularVelocity(LSL_Vector angularVelocity, int local)
+ public void llSetAngularVelocity(LSL_Vector avel, int local)
{
m_host.AddScriptLPS(1);
-
- if (!m_host.ParentGroup.IsDeleted)
- {
- if (local != 0)
- angularVelocity *= llGetRot();
-
- m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity;
- }
+ m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0);
}
-
public LSL_Integer llTarget(LSL_Vector position, double range)
{
m_host.AddScriptLPS(1);
@@ -2613,16 +3060,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.ApplyImpulse(v, local != 0);
}
+
public void llApplyRotationalImpulse(LSL_Vector force, int local)
{
m_host.AddScriptLPS(1);
- m_host.ApplyAngularImpulse(force, local != 0);
+ m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
}
public void llSetTorque(LSL_Vector torque, int local)
{
m_host.AddScriptLPS(1);
- m_host.SetAngularImpulse(torque, local != 0);
+ m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
}
public LSL_Vector llGetTorque()
@@ -2639,20 +3087,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
llSetTorque(torque, local);
}
+
public LSL_Vector llGetVel()
{
m_host.AddScriptLPS(1);
- Vector3 vel;
+ Vector3 vel = Vector3.Zero;
if (m_host.ParentGroup.IsAttachment)
{
ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
- vel = avatar.GetWorldVelocity();
+ if (avatar != null)
+ vel = avatar.GetWorldVelocity();
}
else
{
- vel = m_host.Velocity;
+ vel = m_host.ParentGroup.RootPart.Velocity;
}
return new LSL_Vector(vel);
@@ -2668,8 +3118,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Vector llGetOmega()
{
m_host.AddScriptLPS(1);
-
- return new LSL_Vector(m_host.AngularVelocity);
+ Vector3 avel = m_host.AngularVelocity;
+ return new LSL_Vector(avel.X, avel.Y, avel.Z);
}
public LSL_Float llGetTimeOfDay()
@@ -2687,22 +3137,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Float llGetTime()
{
m_host.AddScriptLPS(1);
- TimeSpan ScriptTime = DateTime.Now - m_timer;
- return (double)(ScriptTime.TotalMilliseconds / 1000);
+ double ScriptTime = Util.GetTimeStampMS() - m_timer;
+ return (float)Math.Round((ScriptTime / 1000.0), 3);
}
public void llResetTime()
{
m_host.AddScriptLPS(1);
- m_timer = DateTime.Now;
+ m_timer = Util.GetTimeStampMS();
}
public LSL_Float llGetAndResetTime()
{
m_host.AddScriptLPS(1);
- TimeSpan ScriptTime = DateTime.Now - m_timer;
- m_timer = DateTime.Now;
- return (double)(ScriptTime.TotalMilliseconds / 1000);
+ double now = Util.GetTimeStampMS();
+ double ScriptTime = now - m_timer;
+ m_timer = now;
+ return (float)Math.Round((ScriptTime / 1000.0), 3);
}
public void llSound(string sound, double volume, int queue, int loop)
@@ -2722,8 +3173,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_SoundModule.SendSound(
m_host.UUID,
- ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
- volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
+ ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
+ volume, false, 0,
0, false, false);
}
}
@@ -2734,7 +3185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (m_SoundModule != null)
{
m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
- volume, 20, false);
+ volume, 20, false,false);
}
}
@@ -2744,16 +3195,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (m_SoundModule != null)
{
m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
- volume, 20, true);
+ volume, 20, true, false);
}
}
public void llLoopSoundSlave(string sound, double volume)
{
m_host.AddScriptLPS(1);
- lock (m_host.ParentGroup.LoopSoundSlavePrims)
+ if (m_SoundModule != null)
{
- m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host);
+ m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
+ volume, 20, false, true);
}
}
@@ -2795,6 +3247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
if (m_SoundModule != null)
m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
+ ScriptSleep(m_sleepMsOnPreloadSound);
}
///
@@ -3027,7 +3480,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return src.ToLower();
}
- public void llGiveMoney(string destination, int amount)
+ public LSL_Integer llGiveMoney(string destination, int amount)
{
Util.FireAndForget(x =>
{
@@ -3058,69 +3511,86 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
}
+ string reason;
money.ObjectGiveMoney(
- m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
+
+ m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero, out reason);
}, null, "LSL_Api.llGiveMoney");
+
+ return 0;
}
public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
{
m_host.AddScriptLPS(1);
Deprecated("llMakeExplosion", "Use llParticleSystem instead");
+ ScriptSleep(m_sleepMsOnMakeExplosion);
}
public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
{
m_host.AddScriptLPS(1);
Deprecated("llMakeFountain", "Use llParticleSystem instead");
+ ScriptSleep(m_sleepMsOnMakeFountain);
}
public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
{
m_host.AddScriptLPS(1);
Deprecated("llMakeSmoke", "Use llParticleSystem instead");
+ ScriptSleep(m_sleepMsOnMakeSmoke);
}
public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
{
m_host.AddScriptLPS(1);
Deprecated("llMakeFire", "Use llParticleSystem instead");
+ ScriptSleep(m_sleepMsOnMakeFire);
}
public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
{
+ doObjectRez(inventory, pos, vel, rot, param, true);
+ }
+
+ public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot)
+ {
m_host.AddScriptLPS(1);
+ if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
+ return;
- Util.FireAndForget(x =>
- {
- if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
- return;
+ float dist = (float)llVecDist(llGetPos(), pos);
- float dist = (float)llVecDist(llGetPos(), pos);
+ if (dist > m_ScriptDistanceFactor * 10.0f)
+ return;
- TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
+ TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
- if (item == null)
- {
- Error("llRezAtRoot", "Can't find object '" + inventory + "'");
- return;
- }
+ if (item == null)
+ {
+ Error("llRez(AtRoot/Object)", "Can't find object '" + inventory + "'");
+ return;
+ }
- if (item.InvType != (int)InventoryType.Object)
- {
- Error("llRezAtRoot", "Can't create requested object; object is missing from database");
- return;
- }
+ if (item.InvType != (int)InventoryType.Object)
+ {
+ Error("llRez(AtRoot/Object)", "Can't create requested object; object is missing from database");
+ return;
+ }
- // need the magnitude later
- // float velmag = (float)Util.GetMagnitude(llvel);
+ Util.FireAndForget(x =>
+ {
- List new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
+ Quaternion wrot = rot;
+ wrot.Normalize();
+ List new_groups = World.RezObject(m_host, item, pos, wrot, vel, param, atRoot);
// If either of these are null, then there was an unknown error.
if (new_groups == null)
return;
+ bool notAttachment = !m_host.ParentGroup.IsAttachment;
+
foreach (SceneObjectGroup group in new_groups)
{
// objects rezzed with this method are die_at_edge by default.
@@ -3134,58 +3604,79 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
group.RootPart.UUID.ToString()) },
new DetectParams[0]));
- float groupmass = group.GetMass();
+ if (notAttachment)
+ {
+ float groupmass = group.GetMass();
- PhysicsActor pa = group.RootPart.PhysActor;
+ PhysicsActor pa = group.RootPart.PhysActor;
- //Recoil.
- if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
- {
- Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
- if (recoil != Vector3.Zero)
+ //Recoil.
+ if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
{
- llApplyImpulse(recoil, 0);
+ Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
+ if (recoil != Vector3.Zero)
+ {
+ llApplyImpulse(recoil, 0);
+ }
}
}
- // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
- }
- }, null, "LSL_Api.llRezAtRoot");
+ }
+ }, null, "LSL_Api.doObjectRez");
+
+ //ScriptSleep((int)((groupmass * velmag) / 10));
+ ScriptSleep(m_sleepMsOnRezAtRoot);
}
public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
{
- llRezAtRoot(inventory, pos, vel, rot, param);
+ doObjectRez(inventory, pos, vel, rot, param, false);
}
public void llLookAt(LSL_Vector target, double strength, double damping)
{
m_host.AddScriptLPS(1);
- // Determine where we are looking from
+
+ // Get the normalized vector to the target
LSL_Vector from = llGetPos();
- // normalized direction to target
+ // normalized direction to target
LSL_Vector dir = llVecNorm(target - from);
+
// use vertical to help compute left axis
- LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
+// LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
// find normalized left axis parallel to horizon
- LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
+// LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
+
+ LSL_Vector left = new LSL_Vector(-dir.y, dir.x, 0.0f);
+ left = llVecNorm(left);
// make up orthogonal to left and dir
- up = LSL_Vector.Cross(dir, left);
+ LSL_Vector up = LSL_Vector.Cross(dir, left);
// compute rotation based on orthogonal axes
+ // and rotate so Z points to target with X below horizont
LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up);
- // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
- // set the rotation of the object, copy that behavior
- PhysicsActor pa = m_host.PhysActor;
+ SceneObjectGroup sog = m_host.ParentGroup;
+ if(sog == null || sog.IsDeleted)
+ return;
- if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical)
+ if (!sog.UsesPhysics || sog.IsAttachment)
{
- llSetRot(rot);
+ // Do nothing if either value is 0 (this has been checked in SL)
+ if (strength <= 0.0 || damping <= 0.0)
+ return;
+
+ llSetLocalRot(rot);
}
else
{
- m_host.StartLookAt(rot, (float)strength, (float)damping);
+ if (strength == 0)
+ {
+ llSetLocalRot(rot);
+ return;
+ }
+
+ sog.StartLookAt(rot, (float)strength, (float)damping);
}
}
@@ -3231,22 +3722,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else
{
- if (m_host.IsRoot)
- {
+ // new SL always returns object mass
+// if (m_host.IsRoot)
+// {
return m_host.ParentGroup.GetMass();
- }
- else
- {
- return m_host.GetMass();
- }
+// }
+// else
+// {
+// return m_host.GetMass();
+// }
}
}
public LSL_Float llGetMassMKS()
{
- // this is what the wiki says it does!
- // http://wiki.secondlife.com/wiki/LlGetMassMKS
- return llGetMass() * 100.0;
+ return 100f * llGetMass();
}
public void llCollisionFilter(string name, string id, int accept)
@@ -3296,7 +3786,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
// Unregister controls from Presence
presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
- // Remove Take Control permission.
+ // Remove Take Control permission.
m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
}
}
@@ -3355,9 +3845,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
-// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
-// return;
-
if (m_item.PermsGranter != m_host.OwnerID)
return;
@@ -3401,6 +3888,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llInstantMessage(string user, string message)
{
m_host.AddScriptLPS(1);
+ UUID result;
+ if (!UUID.TryParse(user, out result) || result == UUID.Zero)
+ {
+ Error("llInstantMessage","An invalid key was passed to llInstantMessage");
+ ScriptSleep(2000);
+ return;
+ }
// We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
// InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
@@ -3411,31 +3905,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// TODO: figure out values for client, fromSession, and imSessionID
// client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
+ UUID friendTransactionID = UUID.Random();
+
+ //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
GridInstantMessage msg = new GridInstantMessage();
msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid;
msg.toAgentID = new Guid(user); // toAgentID.Guid;
msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here
-// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
-// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
- msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
- //if (client != null)
- //{
- msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
- //}
- //else
- //{
- // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
- //}
- // Cap the message length at 1024.
+ msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
+ msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
+
if (message != null && message.Length > 1024)
msg.message = message.Substring(0, 1024);
else
msg.message = message;
- msg.dialog = (byte)19; // messgage from script ??? // dialog;
+ msg.dialog = (byte)19; // MessageFromObject
msg.fromGroup = false;// fromGroup;
msg.offline = (byte)0; //offline;
- msg.ParentEstateID = 0; //ParentEstateID;
+ msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
msg.Position = new Vector3(m_host.AbsolutePosition);
msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
@@ -3452,6 +3940,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
}
+
+ ScriptSleep(m_sleepMsOnInstantMessage);
}
public void llEmail(string address, string subject, string message)
@@ -3489,6 +3979,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
emailModule.SendEmail(m_host.UUID, address, subject, message);
+ ScriptSleep(m_sleepMsOnEmail);
}
public void llGetNextEmail(string address, string subject)
@@ -3551,25 +4042,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- if (m_host.PhysActor != null)
+ PIDHoverType hoverType = PIDHoverType.Ground;
+ if (water != 0)
{
- PIDHoverType hoverType = PIDHoverType.Ground;
- if (water != 0)
- {
- hoverType = PIDHoverType.GroundAndWater;
- }
-
- m_host.SetHoverHeight((float)height, hoverType, (float)tau);
+ hoverType = PIDHoverType.GroundAndWater;
}
+ m_host.SetHoverHeight((float)height, hoverType, (float)tau);
}
public void llStopHover()
{
m_host.AddScriptLPS(1);
- if (m_host.PhysActor != null)
- {
- m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
- }
+ m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
}
public void llMinEventDelay(double delay)
@@ -3598,15 +4082,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Per discussion with Melanie, for non-physical objects llLookAt appears to simply
// set the rotation of the object, copy that behavior
- PhysicsActor pa = m_host.PhysActor;
+ SceneObjectGroup sog = m_host.ParentGroup;
+ if(sog == null || sog.IsDeleted)
+ return;
- if (strength == 0 || pa == null || !pa.IsPhysical)
+ if (strength == 0 || !sog.UsesPhysics || sog.IsAttachment)
{
llSetLocalRot(target);
}
else
{
- m_host.RotLookAt(target, (float)strength, (float)damping);
+ sog.RotLookAt(target, (float)strength, (float)damping);
}
}
@@ -3735,7 +4221,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
ScriptBaseClass.PERMISSION_TRACK_CAMERA |
- ScriptBaseClass.PERMISSION_ATTACH;
+ ScriptBaseClass.PERMISSION_ATTACH |
+ ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS;
}
else
{
@@ -3752,15 +4239,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
}
+ if (World.GetExtraSetting("auto_grant_all_perms") == "true")
+ {
+ implicitPerms = perm;
+ }
}
if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
{
- lock (m_host.TaskInventory)
- {
- m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
- m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
- }
+ m_host.TaskInventory.LockItemsForWrite(true);
+ m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
+ m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
+ m_host.TaskInventory.LockItemsForWrite(false);
m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
"run_time_permissions", new Object[] {
@@ -3771,7 +4261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
ScenePresence presence = World.GetScenePresence(agentID);
-
+
if (presence != null)
{
// If permissions are being requested from an NPC and were not implicitly granted above then
@@ -3804,11 +4294,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!m_waitingForScriptAnswer)
{
- lock (m_host.TaskInventory)
- {
- m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
- m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
- }
+ m_host.TaskInventory.LockItemsForWrite(true);
+ m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
+ m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
+ m_host.TaskInventory.LockItemsForWrite(false);
presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
m_waitingForScriptAnswer=true;
@@ -3837,14 +4326,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
llReleaseControls();
- lock (m_host.TaskInventory)
- {
- m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
- }
+ m_host.TaskInventory.LockItemsForWrite(true);
+ m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
+ m_host.TaskInventory.LockItemsForWrite(false);
- m_ScriptEngine.PostScriptEvent(
- m_item.ItemID,
- new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0]));
+ m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
+ "run_time_permissions", new Object[] {
+ new LSL_Integer(answer) },
+ new DetectParams[0]));
}
public LSL_String llGetPermissionsKey()
@@ -3883,15 +4372,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
{
List parts = GetLinkParts(linknumber);
-
- foreach (SceneObjectPart part in parts)
- part.SetFaceColorAlpha(face, color, null);
+ if (parts.Count > 0)
+ {
+ try
+ {
+ foreach (SceneObjectPart part in parts)
+ part.SetFaceColorAlpha(face, color, null);
+ }
+ finally { }
+ }
}
public void llCreateLink(string target, int parent)
{
m_host.AddScriptLPS(1);
+ UUID targetID;
+
+ if (!UUID.TryParse(target, out targetID))
+ return;
+
if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
&& !m_automaticLinkPermission)
{
@@ -3907,9 +4407,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID targetID;
if (!UUID.TryParse(target, out targetID))
- return;
+ return;
SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID);
+ if (targetPart == null)
+ return;
if (targetPart.ParentGroup.AttachmentPoint != 0)
return; // Fail silently if attached
@@ -3919,24 +4421,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SceneObjectGroup parentPrim = null, childPrim = null;
- if (targetPart != null)
+ if (parent != 0)
{
- if (parent != 0)
- {
- parentPrim = m_host.ParentGroup;
- childPrim = targetPart.ParentGroup;
- }
- else
- {
- parentPrim = targetPart.ParentGroup;
- childPrim = m_host.ParentGroup;
- }
-
- // Required for linking
- childPrim.RootPart.ClearUpdateSchedule();
- parentPrim.LinkToGroup(childPrim, true);
+ parentPrim = m_host.ParentGroup;
+ childPrim = targetPart.ParentGroup;
+ }
+ else
+ {
+ parentPrim = targetPart.ParentGroup;
+ childPrim = m_host.ParentGroup;
}
+ // Required for linking
+ childPrim.RootPart.ClearUpdateSchedule();
+ parentPrim.LinkToGroup(childPrim, true);
+
+
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
parentPrim.RootPart.CreateSelected = true;
parentPrim.HasGroupChanged = true;
@@ -3949,6 +4449,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (client != null)
parentPrim.SendPropertiesToClient(client);
+
+ ScriptSleep(m_sleepMsOnCreateLink);
}
public void llBreakLink(int linknum)
@@ -4005,10 +4507,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Restructuring Multiple Prims.
List parts = new List(parentPrim.Parts);
parts.Remove(parentPrim.RootPart);
- foreach (SceneObjectPart part in parts)
+ if (parts.Count > 0)
{
- parentPrim.DelinkFromGroup(part.LocalId, true);
- }
+ try
+ {
+ foreach (SceneObjectPart part in parts)
+ {
+ parentPrim.DelinkFromGroup(part.LocalId, true);
+ }
+ }
+ finally { }
+ }
+
parentPrim.HasGroupChanged = true;
parentPrim.ScheduleGroupForFullUpdate();
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -4017,12 +4527,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
SceneObjectPart newRoot = parts[0];
parts.Remove(newRoot);
- foreach (SceneObjectPart part in parts)
+
+ try
{
- // Required for linking
- part.ClearUpdateSchedule();
- newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
+ foreach (SceneObjectPart part in parts)
+ {
+ part.ClearUpdateSchedule();
+ newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
+ }
}
+ finally { }
+
newRoot.ParentGroup.HasGroupChanged = true;
newRoot.ParentGroup.ScheduleGroupForFullUpdate();
}
@@ -4043,13 +4558,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
+ TaskInventoryItem item = m_item;
+
+ if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
&& !m_automaticLinkPermission)
{
- Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set");
+ Error("llBreakAllLinks","Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
return;
}
-
BreakAllLinks();
}
@@ -4074,13 +4590,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_String llGetLinkKey(int linknum)
{
m_host.AddScriptLPS(1);
+ SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
+ if (part != null)
+ {
+ return part.UUID.ToString();
+ }
+ else
+ {
+ if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
+ {
+ linknum -= (m_host.ParentGroup.PrimCount) + 1;
- ISceneEntity entity = GetLinkEntity(m_host, linknum);
+ if (linknum < 0)
+ return UUID.Zero.ToString();
- if (entity != null)
- return entity.UUID.ToString();
- else
- return ScriptBaseClass.NULL_KEY;
+ List avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
+ if (avatars.Count > linknum)
+ {
+ return avatars[linknum].UUID.ToString();
+ }
+ }
+ return UUID.Zero.ToString();
+ }
}
///
@@ -4139,17 +4670,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
int count = 0;
- lock (m_host.TaskInventory)
+ m_host.TaskInventory.LockItemsForRead(true);
+ foreach (KeyValuePair inv in m_host.TaskInventory)
{
- foreach (KeyValuePair inv in m_host.TaskInventory)
+ if (inv.Value.Type == type || type == -1)
{
- if (inv.Value.Type == type || type == -1)
- {
- count = count + 1;
- }
+ count = count + 1;
}
}
+ m_host.TaskInventory.LockItemsForRead(false);
return count;
}
@@ -4158,16 +4688,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
ArrayList keys = new ArrayList();
- lock (m_host.TaskInventory)
+ m_host.TaskInventory.LockItemsForRead(true);
+ foreach (KeyValuePair inv in m_host.TaskInventory)
{
- foreach (KeyValuePair inv in m_host.TaskInventory)
+ if (inv.Value.Type == type || type == -1)
{
- if (inv.Value.Type == type || type == -1)
- {
- keys.Add(inv.Value.Name);
- }
+ keys.Add(inv.Value.Name);
}
}
+ m_host.TaskInventory.LockItemsForRead(false);
if (keys.Count == 0)
{
@@ -4237,35 +4766,49 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
}
+
// destination is an avatar
string message;
InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message);
if (agentItem == null)
{
- llSay(0, message);
+ llSay(0, message);
return;
}
- if (m_TransferModule != null)
- {
- byte[] bucket = new byte[1];
- bucket[0] = (byte)item.Type;
+ byte[] bucket = new byte[1];
+ bucket[0] = (byte)item.Type;
+ //byte[] objBytes = agentItem.ID.GetBytes();
+ //Array.Copy(objBytes, 0, bucket, 1, 16);
+
+ GridInstantMessage msg = new GridInstantMessage(World,
+ m_host.OwnerID, m_host.Name, destId,
+ (byte)InstantMessageDialog.TaskInventoryOffered,
+ false, item.Name+". "+m_host.Name+" is located at "+
+ World.RegionInfo.RegionName+" "+
+ m_host.AbsolutePosition.ToString(),
+ agentItem.ID, true, m_host.AbsolutePosition,
+ bucket, true);
- GridInstantMessage msg = new GridInstantMessage(World,
- m_host.OwnerID, m_host.Name, destId,
- (byte)InstantMessageDialog.TaskInventoryOffered,
- false, item.Name+". "+m_host.Name+" is located at "+
- World.RegionInfo.RegionName+" "+
- m_host.AbsolutePosition.ToString(),
- agentItem.ID, true, m_host.AbsolutePosition,
- bucket, true);
+ ScenePresence sp;
- m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
+ if (World.TryGetScenePresence(destId, out sp))
+ {
+ sp.ControllingClient.SendInstantMessage(msg);
+ }
+ else
+ {
+ if (m_TransferModule != null)
+ m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
}
+
+ //This delay should only occur when giving inventory to avatars.
+ ScriptSleep(m_sleepMsOnGiveInventory);
}
}
+ [DebuggerNonUserCode]
public void llRemoveInventory(string name)
{
m_host.AddScriptLPS(1);
@@ -4285,20 +4828,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
- if (text.Length > 254)
- text = text.Remove(254);
-
byte[] data;
- do
- {
- data = Util.UTF8.GetBytes(text);
- if (data.Length > 254)
- text = text.Substring(0, text.Length - 1);
- } while (data.Length > 254);
-
+ data = Util.StringToBytes256(text);
+ text = Util.UTF8.GetString(data);
m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
- //m_host.ParentGroup.HasGroupChanged = true;
- //m_host.ParentGroup.ScheduleGroupForFullUpdate();
}
public LSL_Float llWater(LSL_Vector offset)
@@ -4320,14 +4853,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- UUID uuid = (UUID)id;
- PresenceInfo pinfo = null;
- UserAccount account;
-
- UserInfoCacheEntry ce;
-
- lock (m_userInfoCache)
+ UUID uuid;
+ if (UUID.TryParse(id, out uuid))
{
+ PresenceInfo pinfo = null;
+ UserAccount account;
+
+ UserInfoCacheEntry ce;
if (!m_userInfoCache.TryGetValue(uuid, out ce))
{
account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
@@ -4353,7 +4885,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ce.time = Util.EnvironmentTickCount();
ce.account = account;
ce.pinfo = pinfo;
-
m_userInfoCache[uuid] = ce;
}
else
@@ -4362,77 +4893,78 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return UUID.Zero.ToString();
account = ce.account;
+ pinfo = ce.pinfo;
+ }
- if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time)
- >= LlRequestAgentDataCacheTimeoutMs)
+ if (Util.EnvironmentTickCount() < ce.time ||
+ (Util.EnvironmentTickCount() - ce.time) >= LlRequestAgentDataCacheTimeoutMs)
+ {
+ PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
+ if (pinfos != null && pinfos.Length > 0)
{
- PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
- if (pinfos != null && pinfos.Length > 0)
+ foreach (PresenceInfo p in pinfos)
{
- foreach (PresenceInfo p in pinfos)
+ if (p.RegionID != UUID.Zero)
{
- if (p.RegionID != UUID.Zero)
- {
- pinfo = p;
- }
+ pinfo = p;
}
}
- else
- {
- pinfo = null;
- }
-
- ce.time = Util.EnvironmentTickCount();
- ce.pinfo = pinfo;
}
else
- {
- pinfo = ce.pinfo;
- }
+ pinfo = null;
+
+ ce.time = Util.EnvironmentTickCount();
+ ce.pinfo = pinfo;
}
- }
- string reply = String.Empty;
+ string reply = String.Empty;
- switch (data)
- {
- case ScriptBaseClass.DATA_ONLINE:
- if (pinfo != null && pinfo.RegionID != UUID.Zero)
- reply = "1";
- else
- reply = "0";
- break;
- case ScriptBaseClass.DATA_NAME: // (First Last)
- reply = account.FirstName + " " + account.LastName;
- break;
- case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD)
- DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
- born = born.AddSeconds(account.Created);
- reply = born.ToString("yyyy-MM-dd");
- break;
- case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0)
- reply = "0,0,0,0,0,0";
- break;
- case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant.
- reply = account.UserLevel.ToString();
- break;
- case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3)
- reply = "0";
- break;
- default:
- return UUID.Zero.ToString(); // Raise no event
- }
+ switch (data)
+ {
+ case ScriptBaseClass.DATA_ONLINE: // DATA_ONLINE (0|1)
+ if (pinfo != null && pinfo.RegionID != UUID.Zero)
+ reply = "1";
+ else
+ reply = "0";
+ break;
+ case ScriptBaseClass.DATA_NAME: // DATA_NAME (First Last)
+ reply = account.FirstName + " " + account.LastName;
+ break;
+ case ScriptBaseClass.DATA_BORN: // DATA_BORN (YYYY-MM-DD)
+ DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
+ born = born.AddSeconds(account.Created);
+ reply = born.ToString("yyyy-MM-dd");
+ break;
+ case ScriptBaseClass.DATA_RATING: // DATA_RATING (0,0,0,0,0,0)
+ reply = "0,0,0,0,0,0";
+ break;
+ case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant.
+ reply = account.UserLevel.ToString();
+ break;
+ case ScriptBaseClass.DATA_PAYINFO: // DATA_PAYINFO (0|1|2|3)
+ reply = "0";
+ break;
+ default:
+ return UUID.Zero.ToString(); // Raise no event
+ }
- UUID rq = UUID.Random();
+ UUID rq = UUID.Random();
- UUID tid = AsyncCommands.
- DataserverPlugin.RegisterRequest(m_host.LocalId,
- m_item.ItemID, rq.ToString());
+ UUID tid = AsyncCommands.
+ DataserverPlugin.RegisterRequest(m_host.LocalId,
+ m_item.ItemID, rq.ToString());
- AsyncCommands.
- DataserverPlugin.DataserverReply(rq.ToString(), reply);
+ AsyncCommands.
+ DataserverPlugin.DataserverReply(rq.ToString(), reply);
- return tid.ToString();
+ ScriptSleep(m_sleepMsOnRequestAgentData);
+ return tid.ToString();
+ }
+ else
+ {
+ Error("llRequestAgentData","Invalid UUID passed to llRequestAgentData.");
+ }
+ return "";
}
public LSL_String llRequestInventoryData(string name)
@@ -4464,10 +4996,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
reply);
});
+ ScriptSleep(m_sleepMsOnRequestInventoryData);
return tid.ToString();
}
}
+ ScriptSleep(m_sleepMsOnRequestInventoryData);
return String.Empty;
}
@@ -4484,15 +5018,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (UUID.TryParse(agent, out agentId))
{
ScenePresence presence = World.GetScenePresence(agentId);
- if (presence != null)
+ if (presence != null && presence.PresenceType != PresenceType.Npc)
{
+ // agent must not be a god
+ if (presence.GodController.UserLevel >= 200) return;
+
// agent must be over the owners land
if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
{
- World.TeleportClientHome(agentId, presence.ControllingClient);
+ if (!World.TeleportClientHome(agentId, presence.ControllingClient))
+ {
+ // They can't be teleported home for some reason
+ GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
+ if (regionInfo != null)
+ {
+ World.RequestTeleportLocation(
+ presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
+ (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
+ }
+ }
}
}
}
+
+ ScriptSleep(m_sleepMsOnSetDamage);
}
public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
@@ -4505,20 +5054,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ScenePresence presence = World.GetScenePresence(agentId);
if (presence != null && presence.PresenceType != PresenceType.Npc)
{
- // agent must not be a god
- if (presence.GodLevel >= 200) return;
-
if (destination == String.Empty)
destination = World.RegionInfo.RegionName;
- // agent must be over the owners land
- if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
+ if (m_item.PermsGranter == agentId)
+ {
+ if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0)
+ {
+ DoLLTeleport(presence, destination, targetPos, targetLookAt);
+ }
+ }
+
+ // agent must be wearing the object
+ if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
{
DoLLTeleport(presence, destination, targetPos, targetLookAt);
}
- else // or must be wearing the prim
+ else
{
- if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
+ // agent must not be a god
+ if (presence.IsViewerUIGod) return;
+
+ // agent must be over the owners land
+ ILandObject agentLand = World.LandChannel.GetLandObject(presence.AbsolutePosition);
+ ILandObject objectLand = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
+ if (m_host.OwnerID == objectLand.LandData.OwnerID && m_host.OwnerID == agentLand.LandData.OwnerID)
{
DoLLTeleport(presence, destination, targetPos, targetLookAt);
}
@@ -4536,23 +5096,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (UUID.TryParse(agent, out agentId))
{
+ // This function is owner only!
+ if (m_host.OwnerID != agentId)
+ return;
+
ScenePresence presence = World.GetScenePresence(agentId);
- if (presence != null && presence.PresenceType != PresenceType.Npc)
+
+ if (presence == null || presence.PresenceType == PresenceType.Npc)
+ return;
+
+ // Can't TP sitting avatars
+ if (presence.ParentID != 0) // Sitting
+ return;
+
+ if (m_item.PermsGranter == agentId)
{
- // agent must not be a god
- if (presence.GodLevel >= 200) return;
+ // If attached using llAttachToAvatarTemp, cowardly refuse
+ if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.ParentGroup.FromItemID == UUID.Zero)
+ return;
- // agent must be over the owners land
- if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
- {
- World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
- }
- else // or must be wearing the prim
+ if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0)
{
- if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
- {
- World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
- }
+ World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
}
}
}
@@ -4601,13 +5166,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
Error("llTextBox", "Empty message");
}
- else if (message.Length > 512)
+ else if (Encoding.UTF8.GetByteCount(message) > 512)
{
- Error("llTextBox", "Message more than 512 characters");
+ Error("llTextBox", "Message longer than 512 bytes");
}
else
{
dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID);
+ ScriptSleep(m_sleepMsOnTextBox);
}
}
@@ -4625,9 +5191,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
+ if(impact_sound == "")
+ {
+ m_host.CollisionSoundVolume = (float)impact_volume;
+ m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
+ m_host.CollisionSoundType = -1; // disable all sounds
+ m_host.aggregateScriptEvents();
+ return;
+ }
+
// TODO: Parameter check logic required.
- m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
- m_host.CollisionSoundVolume = (float)impact_volume;
+ UUID soundId = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
+ if(soundId != UUID.Zero)
+ {
+ m_host.CollisionSound = soundId;
+ m_host.CollisionSoundVolume = (float)impact_volume;
+ m_host.CollisionSoundType = 1;
+ }
+ else
+ m_host.CollisionSoundType = -1;
+
+ m_host.aggregateScriptEvents();
}
public LSL_String llGetAnimation(string id)
@@ -4641,14 +5225,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (m_host.RegionHandle == presence.RegionHandle)
{
- Dictionary animationstateNames = DefaultAvatarAnimations.AnimStateNames;
-
if (presence != null)
{
- AnimationSet currentAnims = presence.Animator.Animations;
- string currentAnimationState = String.Empty;
- if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState))
- return currentAnimationState;
+// if (presence.SitGround)
+// return "Sitting on Ground";
+// if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
+// return "Sitting";
+
+ string movementAnimation = presence.Animator.CurrentMovementAnimation;
+ string lslMovementAnimation;
+
+ if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
+ return lslMovementAnimation;
}
}
@@ -4712,7 +5300,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
// Pushee is in GodMode this pushing object isn't owned by them
- if (avatar.GodLevel > 0 && m_host.OwnerID != targetID)
+ if (avatar.IsViewerUIGod && m_host.OwnerID != targetID)
return;
pusheeav = avatar;
@@ -4796,7 +5384,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
float distance = (PusheePos - m_host.AbsolutePosition).Length();
float distance_term = distance * distance * distance; // Script Energy
- float pusher_mass = m_host.GetMass();
+ // use total object mass and not part
+ float pusher_mass = m_host.ParentGroup.GetMass();
float PUSH_ATTENUATION_DISTANCE = 17f;
float PUSH_ATTENUATION_SCALE = 5f;
@@ -4831,7 +5420,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
if (local != 0)
{
- applied_linear_impulse *= m_host.GetWorldRotation();
+// applied_linear_impulse *= m_host.GetWorldRotation();
+ applied_linear_impulse *= pusheeav.GetWorldRotation();
}
pa.AddForce(applied_linear_impulse, true);
@@ -4891,20 +5481,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- return GetNumberOfSides(m_host);
+ return m_host.GetNumberOfSides();
}
protected int GetNumberOfSides(SceneObjectPart part)
{
- int sides = part.GetNumberOfSides();
-
- if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0)
- {
- // Make up for a bug where LSL shows 4 sides rather than 2
- sides += 2;
- }
-
- return sides;
+ return part.GetNumberOfSides();
}
@@ -4959,20 +5541,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- if (Math.Abs(rot.s) > 1) // normalization needed
- rot.Normalize();
+ rot.Normalize();
double s = Math.Sqrt(1 - rot.s * rot.s);
- if (s < 0.001)
- {
- return new LSL_Vector(1, 0, 0);
- }
- else
- {
- double invS = 1.0 / s;
- if (rot.s < 0) invS = -invS;
- return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
- }
+ if (s < 1e-8)
+ return new LSL_Vector(0, 0, 0);
+
+ double invS = 1.0 / s;
+ if (rot.s < 0)
+ invS = -invS;
+ return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
}
@@ -4981,11 +5559,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- if (Math.Abs(rot.s) > 1) // normalization needed
- rot.Normalize();
+ rot.Normalize();
double angle = 2 * Math.Acos(rot.s);
- if (angle > Math.PI)
+ if (angle > Math.PI)
angle = 2 * Math.PI - angle;
return angle;
@@ -5185,43 +5762,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- if (src == null)
- {
- return 0;
- }
- else
- {
- return src.Length;
- }
+ return src.Length;
}
public LSL_Integer llList2Integer(LSL_List src, int index)
{
m_host.AddScriptLPS(1);
if (index < 0)
- {
index = src.Length + index;
- }
+
if (index >= src.Length || index < 0)
- {
return 0;
- }
+
+ object item = src.Data[index];
// Vectors & Rotations always return zero in SL, but
// keys don't always return zero, it seems to be a bit complex.
- else if (src.Data[index] is LSL_Vector ||
- src.Data[index] is LSL_Rotation)
- {
+ if (item is LSL_Vector || item is LSL_Rotation)
return 0;
- }
+
try
{
-
- if (src.Data[index] is LSL_Integer)
- return (LSL_Integer)src.Data[index];
- else if (src.Data[index] is LSL_Float)
- return Convert.ToInt32(((LSL_Float)src.Data[index]).value);
- return new LSL_Integer(src.Data[index].ToString());
+ if (item is LSL_Integer)
+ return (LSL_Integer)item;
+ else if (item is LSL_Float)
+ return Convert.ToInt32(((LSL_Float)item).value);;
+ return new LSL_Integer(item.ToString());
}
catch (FormatException)
{
@@ -5233,38 +5799,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
if (index < 0)
- {
index = src.Length + index;
- }
+
if (index >= src.Length || index < 0)
- {
- return 0.0;
- }
+ return 0;
+
+ object item = src.Data[index];
// Vectors & Rotations always return zero in SL
- else if (src.Data[index] is LSL_Vector ||
- src.Data[index] is LSL_Rotation)
- {
+ if(item is LSL_Vector || item is LSL_Rotation)
return 0;
- }
+
// valid keys seem to get parsed as integers then converted to floats
- else
+ if (item is LSL_Key)
{
UUID uuidt;
- if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt))
- {
- return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value);
- }
+ string s = item.ToString();
+ if(UUID.TryParse(s, out uuidt))
+ return Convert.ToDouble(new LSL_Integer(s).value);
+// we can't do this because a string is also a LSL_Key for now :(
+// else
+// return 0;
}
+
try
{
- if (src.Data[index] is LSL_Integer)
- return Convert.ToDouble(((LSL_Integer)src.Data[index]).value);
- else if (src.Data[index] is LSL_Float)
- return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
- else if (src.Data[index] is LSL_String)
- return Convert.ToDouble(((LSL_String)src.Data[index]).m_string);
- return Convert.ToDouble(src.Data[index]);
+ if (item is LSL_Integer)
+ return Convert.ToDouble(((LSL_Integer)item).value);
+ else if (item is LSL_Float)
+ return Convert.ToDouble(((LSL_Float)item).value);
+ else if (item is LSL_String)
+ {
+ string str = ((LSL_String)item).m_string;
+ Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
+ if (m != Match.Empty)
+ {
+ str = m.Value;
+ double d = 0.0;
+ if (!Double.TryParse(str, out d))
+ return 0.0;
+ return d;
+ }
+ return 0.0;
+ }
+ return Convert.ToDouble(item);
}
catch (FormatException)
{
@@ -5276,13 +5854,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
if (index < 0)
- {
index = src.Length + index;
- }
+
if (index >= src.Length || index < 0)
- {
return String.Empty;
- }
+
return src.Data[index].ToString();
}
@@ -5290,14 +5866,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
if (index < 0)
- {
index = src.Length + index;
- }
if (index >= src.Length || index < 0)
- {
- return "";
- }
+ return String.Empty;
+
+ object item = src.Data[index];
// SL spits out an empty string for types other than key & string
// At the time of patching, LSL_Key is currently LSL_String,
@@ -5306,31 +5880,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// as it's own struct
// NOTE: 3rd case is needed because a NULL_KEY comes through as
// type 'obj' and wrongly returns ""
- else if (!(src.Data[index] is LSL_String ||
- src.Data[index] is LSL_Key ||
- src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000"))
+ if (!(item is LSL_String ||
+ item is LSL_Key ||
+ item.ToString() == "00000000-0000-0000-0000-000000000000"))
{
- return "";
+ return String.Empty;
}
- return src.Data[index].ToString();
+ return item.ToString();
}
public LSL_Vector llList2Vector(LSL_List src, int index)
{
m_host.AddScriptLPS(1);
if (index < 0)
- {
index = src.Length + index;
- }
+
if (index >= src.Length || index < 0)
- {
return new LSL_Vector(0, 0, 0);
- }
- if (src.Data[index].GetType() == typeof(LSL_Vector))
- {
- return (LSL_Vector)src.Data[index];
- }
+
+ object item = src.Data[index];
+
+ if (item.GetType() == typeof(LSL_Vector))
+ return (LSL_Vector)item;
// SL spits always out ZERO_VECTOR for anything other than
// strings or vectors. Although keys always return ZERO_VECTOR,
@@ -5338,28 +5910,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// a string, a key as string and a string that by coincidence
// is a string, so we're going to leave that up to the
// LSL_Vector constructor.
- else if (!(src.Data[index] is LSL_String ||
- src.Data[index] is LSL_Vector))
- {
- return new LSL_Vector(0, 0, 0);
- }
- else
- {
- return new LSL_Vector(src.Data[index].ToString());
- }
+ if(item is LSL_Vector)
+ return (LSL_Vector) item;
+
+ if (item is LSL_String)
+ return new LSL_Vector(item.ToString());
+
+ return new LSL_Vector(0, 0, 0);
}
public LSL_Rotation llList2Rot(LSL_List src, int index)
{
m_host.AddScriptLPS(1);
if (index < 0)
- {
index = src.Length + index;
- }
+
if (index >= src.Length || index < 0)
- {
return new LSL_Rotation(0, 0, 0, 1);
- }
+
+ object item = src.Data[index];
// SL spits always out ZERO_ROTATION for anything other than
// strings or vectors. Although keys always return ZERO_ROTATION,
@@ -5367,19 +5936,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// a string, a key as string and a string that by coincidence
// is a string, so we're going to leave that up to the
// LSL_Rotation constructor.
- else if (!(src.Data[index] is LSL_String ||
- src.Data[index] is LSL_Rotation))
- {
- return new LSL_Rotation(0, 0, 0, 1);
- }
- else if (src.Data[index].GetType() == typeof(LSL_Rotation))
- {
- return (LSL_Rotation)src.Data[index];
- }
- else
- {
+
+ if (item.GetType() == typeof(LSL_Rotation))
+ return (LSL_Rotation)item;
+
+ if (item is LSL_String)
return new LSL_Rotation(src.Data[index].ToString());
- }
+
+ return new LSL_Rotation(0, 0, 0, 1);
}
public LSL_List llList2List(LSL_List src, int start, int end)
@@ -5567,7 +6131,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
}
- else {
+ else
+ {
object[] array = new object[src.Length];
Array.Copy(src.Data, 0, array, 0, src.Length);
result = new LSL_List(array);
@@ -5674,7 +6239,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Integer llGetRegionAgentCount()
{
m_host.AddScriptLPS(1);
- return new LSL_Integer(World.GetRootAgentCount());
+
+ int count = 0;
+ World.ForEachRootScenePresence(delegate(ScenePresence sp) {
+ count++;
+ });
+
+ return new LSL_Integer(count);
}
public LSL_Vector llGetRegionCorner()
@@ -5742,10 +6313,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
IUrlModule UrlModule = World.RequestModuleInterface();
return UrlModule.ExternalHostNameForLSL;
}
+ else if (name == "region_max_prims")
+ {
+ return World.RegionInfo.ObjectCapacity.ToString();
+ }
+ else if (name == "region_object_bonus")
+ {
+ return World.RegionInfo.RegionSettings.ObjectBonus.ToString();
+ }
else
{
return "";
}
+
}
///
@@ -5821,17 +6401,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
for (int i = 0; i < length; i++)
{
+ int needle = llGetListEntryType(test, 0).value;
+ int haystack = llGetListEntryType(src, i).value;
+
// Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
// rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
// and so the comparison fails even if the LSL_Integer conceptually has the same value.
// Therefore, here we test Equals on both the source and destination objects.
// However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
- if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
+ if ((needle == haystack) && (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])))
{
int j;
for (j = 1; j < test.Length; j++)
- if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j])))
+ {
+ needle = llGetListEntryType(test, j).value;
+ haystack = llGetListEntryType(src, i+j).value;
+
+ if ((needle != haystack) || (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))))
break;
+ }
if (j == test.Length)
{
@@ -5869,64 +6457,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- // edge will be used to pass the Region Coordinates offset
- // we want to check for a neighboring sim
- LSL_Vector edge = new LSL_Vector(0, 0, 0);
+ if(dir.x == 0 && dir.y == 0)
+ return 1; // SL wiki
+
+ float rsx = World.RegionInfo.RegionSizeX;
+ float rsy = World.RegionInfo.RegionSizeY;
+
+ // can understand what sl does if position is not in region, so do something :)
+ float px = (float)Util.Clamp(pos.x, 0.5, rsx - 0.5);
+ float py = (float)Util.Clamp(pos.y, 0.5, rsy - 0.5);
+
+ float ex, ey;
if (dir.x == 0)
{
- if (dir.y == 0)
- {
- // Direction vector is 0,0 so return
- // false since we're staying in the sim
- return 0;
- }
- else
- {
- // Y is the only valid direction
- edge.y = dir.y / Math.Abs(dir.y);
- }
+ ex = px;
+ ey = dir.y > 0 ? rsy + 1.0f : -1.0f;
+ }
+ else if(dir.y == 0)
+ {
+ ex = dir.x > 0 ? rsx + 1.0f : -1.0f;
+ ey = py;
}
else
{
- LSL_Float mag;
- if (dir.x > 0)
- {
- mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
- }
- else
- {
- mag = (pos.x/dir.x);
- }
-
- mag = Math.Abs(mag);
+ float dx = (float) dir.x;
+ float dy = (float) dir.y;
- edge.y = pos.y + (dir.y * mag);
+ float t1 = dx * dx + dy * dy;
+ t1 = (float)Math.Sqrt(t1);
+ dx /= t1;
+ dy /= t1;
- if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
- {
- // Y goes out of bounds first
- edge.y = dir.y / Math.Abs(dir.y);
- }
+ if(dx > 0)
+ t1 = (rsx + 1f - px)/dx;
else
- {
- // X goes out of bounds first or its a corner exit
- edge.y = 0;
- edge.x = dir.x / Math.Abs(dir.x);
- }
- }
+ t1 = -(px + 1f)/dx;
- List neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID);
+ float t2;
+ if(dy > 0)
+ t2 = (rsy + 1f - py)/dy;
+ else
+ t2 = -(py + 1f)/dy;
- uint neighborX = World.RegionInfo.RegionLocX + (uint)dir.x;
- uint neighborY = World.RegionInfo.RegionLocY + (uint)dir.y;
+ if(t1 > t2)
+ t1 = t2;
- foreach (GridRegion sri in neighbors)
- {
- if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY)
- return 0;
+ ex = px + t1 * dx;
+ ey = py + t1 * dy;
}
+ ex += World.RegionInfo.WorldLocX;
+ ey += World.RegionInfo.WorldLocY;
+
+ if(World.GridService.GetRegionByPosition(World.RegionInfo.ScopeID, (int)ex, (int)ey) != null)
+ return 0;
return 1;
}
@@ -5980,6 +6565,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
flags |= ScriptBaseClass.AGENT_AWAY;
}
+ UUID busy = new UUID("efcf670c-2d18-8128-973a-034ebc806b67");
+ UUID[] anims = agent.Animator.GetAnimationArray();
+ if (Array.Exists(anims, a => { return a == busy; }))
+ {
+ flags |= ScriptBaseClass.AGENT_BUSY;
+ }
+
// seems to get unset, even if in mouselook, when avatar is sitting on a prim???
if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
{
@@ -6027,6 +6619,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
flags |= ScriptBaseClass.AGENT_SITTING;
}
+ if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
+ {
+ flags |= ScriptBaseClass.AGENT_MALE;
+ }
+
return flags;
}
@@ -6056,11 +6653,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// AGENT_LIST_PARCEL - all in the same parcel as the scripted object
/// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the
/// current parcel.
+ /// AGENT_LIST_EXCLUDENPC ignore NPCs (bit mask)
///
public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options)
{
m_host.AddScriptLPS(1);
+ // do our bit masks part
+ bool noNPC = (scope & ScriptBaseClass.AGENT_LIST_EXCLUDENPC) !=0;
+
+ // remove bit masks part
+ scope &= ~ ScriptBaseClass.AGENT_LIST_EXCLUDENPC;
+
// the constants are 1, 2 and 4 so bits are being set, but you
// get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4
bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION;
@@ -6101,8 +6705,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
World.ForEachRootScenePresence(
delegate (ScenePresence ssp)
{
+ if(noNPC && ssp.IsNPC)
+ return;
+
// Gods are not listed in SL
- if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent)
+ if (!ssp.IsDeleted && !ssp.IsViewerUIGod && !ssp.IsChildAgent)
{
if (!regionWide)
{
@@ -6135,6 +6742,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
m_host.AdjustSoundGain(volume);
+ ScriptSleep(m_sleepMsOnAdjustSoundVolume);
}
public void llSetSoundRadius(double radius)
@@ -6180,11 +6788,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
List parts = GetLinkParts(linknumber);
- foreach (SceneObjectPart part in parts)
+ try
{
- SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
+ foreach (SceneObjectPart part in parts)
+ {
+ SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
+ }
}
- }
+ finally
+ {
+ }
+ }
private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
{
@@ -6236,10 +6850,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (m_host.OwnerID == land.LandData.OwnerID)
{
- World.TeleportClientHome(agentID, presence.ControllingClient);
+ Vector3 p = World.GetNearestAllowedPosition(presence, land);
+ presence.TeleportOnEject(p);
+ presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
}
}
}
+ ScriptSleep(m_sleepMsOnEjectFromLand);
+ }
+
+ public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
+ {
+ return ParseString2List(str, separators, in_spacers, false);
}
public LSL_Integer llOverMyLand(string id)
@@ -6294,26 +6916,59 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else
{
- agentSize = GetAgentSize(avatar);
+// agentSize = new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight);
+ Vector3 s = avatar.Appearance.AvatarSize;
+ agentSize = new LSL_Vector(s.X, s.Y, s.Z);
}
-
return agentSize;
}
- public LSL_Integer llSameGroup(string agent)
+ public LSL_Integer llSameGroup(string id)
{
m_host.AddScriptLPS(1);
- UUID agentId = new UUID();
- if (!UUID.TryParse(agent, out agentId))
- return new LSL_Integer(0);
- ScenePresence presence = World.GetScenePresence(agentId);
- if (presence == null || presence.IsChildAgent) // Return flase for child agents
+ UUID uuid = new UUID();
+ if (!UUID.TryParse(id, out uuid))
return new LSL_Integer(0);
- IClientAPI client = presence.ControllingClient;
- if (m_host.GroupID == client.ActiveGroupId)
+
+ // Check if it's a group key
+ if (uuid == m_host.ParentGroup.RootPart.GroupID)
return new LSL_Integer(1);
- else
+
+ // Handle object case
+ SceneObjectPart part = World.GetSceneObjectPart(uuid);
+ if (part != null)
+ {
+
+ if(part.ParentGroup.IsAttachment)
+ {
+ uuid = part.ParentGroup.AttachedAvatar;
+ }
+ else
+ {
+ // This will handle both deed and non-deed and also the no
+ // group case
+ if (part.ParentGroup.RootPart.GroupID == m_host.ParentGroup.RootPart.GroupID)
+ return new LSL_Integer(1);
+
+ return new LSL_Integer(0);
+ }
+ }
+
+ // Handle the case where id names an avatar
+ ScenePresence presence = World.GetScenePresence(uuid);
+ if (presence != null)
+ {
+ if (presence.IsChildAgent)
+ return new LSL_Integer(0);
+
+ IClientAPI client = presence.ControllingClient;
+ if (m_host.ParentGroup.RootPart.GroupID == client.ActiveGroupId)
+ return new LSL_Integer(1);
+
return new LSL_Integer(0);
+ }
+
+ return new LSL_Integer(0);
}
public void llUnSit(string id)
@@ -6441,6 +7096,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return m_host.ParentGroup.AttachmentPoint;
}
+ public LSL_List llGetAttachedList(string id)
+ {
+ m_host.AddScriptLPS(1);
+
+ ScenePresence av = World.GetScenePresence((UUID)id);
+
+ if (av == null || av.IsDeleted)
+ return new LSL_List("NOT_FOUND");
+
+ if (av.IsChildAgent || av.IsInTransit)
+ return new LSL_List("NOT_ON_REGION");
+
+ LSL_List AttachmentsList = new LSL_List();
+ List Attachments;
+
+ Attachments = av.GetAttachments();
+
+ foreach (SceneObjectGroup Attachment in Attachments)
+ {
+ if(Attachment.HasPrivateAttachmentPoint)
+ continue;
+ AttachmentsList.Add(new LSL_Key(Attachment.UUID.ToString()));
+ }
+
+ return AttachmentsList;
+ }
+
public virtual LSL_Integer llGetFreeMemory()
{
m_host.AddScriptLPS(1);
@@ -7127,6 +7809,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
{
+ // LSL quaternions can normalize to 0, normal Quaternions can't.
+ if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
+ rot.s = 1; // ZERO_ROTATION = 0,0,0,1
+
part.SitTargetPosition = offset;
part.SitTargetOrientation = rot;
part.ParentGroup.HasGroupChanged = true;
@@ -7166,11 +7852,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
if(linknum == ScriptBaseClass.LINK_SET ||
- linknum == ScriptBaseClass.LINK_ALL_CHILDREN ||
- linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString();
+ linknum == ScriptBaseClass.LINK_ALL_CHILDREN ||
+ linknum == ScriptBaseClass.LINK_ALL_OTHERS ||
+ linknum == 0)
+ return UUID.Zero.ToString();
List parts = GetLinkParts(linknum);
- if (parts.Count == 0) return UUID.Zero.ToString();
+ if (parts.Count == 0)
+ return UUID.Zero.ToString();
return parts[0].SitTargetAvatar.ToString();
}
@@ -7181,7 +7870,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID key;
ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
- if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
+ if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManagePasses, false))
{
int expires = 0;
if (hours != 0)
@@ -7214,6 +7903,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
}
}
+ ScriptSleep(m_sleepMsOnAddToLandPassList);
}
public void llSetTouchText(string text)
@@ -7295,7 +7985,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Integer llScriptDanger(LSL_Vector pos)
{
m_host.AddScriptLPS(1);
- bool result = World.ScriptDanger(m_host.LocalId, pos);
+ bool result = World.LSLScriptDanger(m_host, pos);
if (result)
{
return 1;
@@ -7304,7 +7994,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
return 0;
}
-
}
public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
@@ -7321,35 +8010,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
Error("llDialog", "First parameter must be a key");
return;
}
- if (buttons.Length < 1)
+
+ int length = buttons.Length;
+ if (length < 1)
{
Error("llDialog", "At least 1 button must be shown");
return;
}
- if (buttons.Length > 12)
+ if (length > 12)
{
Error("llDialog", "No more than 12 buttons can be shown");
return;
}
- string[] buts = new string[buttons.Length];
- for (int i = 0; i < buttons.Length; i++)
+
+ if (message == string.Empty)
+ {
+ Error("llDialog", "Empty message");
+ }
+ else if (Encoding.UTF8.GetByteCount(message) > 512)
+ {
+ Error("llDialog", "Message longer than 512 bytes");
+ }
+
+ string[] buts = new string[length];
+ for (int i = 0; i < length; i++)
{
if (buttons.Data[i].ToString() == String.Empty)
{
Error("llDialog", "Button label cannot be blank");
return;
}
+/*
if (buttons.Data[i].ToString().Length > 24)
{
Error("llDialog", "Button label cannot be longer than 24 characters");
return;
}
+*/
buts[i] = buttons.Data[i].ToString();
}
dm.SendDialogToUser(
av, m_host.Name, m_host.UUID, m_host.OwnerID,
message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
+
+ ScriptSleep(m_sleepMsOnDialog);
}
public void llVolumeDetect(int detect)
@@ -7364,6 +8069,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead");
+ ScriptSleep(m_sleepMsOnRemoteLoadScript);
}
public void llSetRemoteScriptAccessPin(int pin)
@@ -7400,8 +8106,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
}
- // the rest of the permission checks are done in RezScript, so check the pin there as well
- World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
+ SceneObjectPart dest = World.GetSceneObjectPart(destId);
+ if (dest != null)
+ {
+ if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
+ {
+ // the rest of the permission checks are done in RezScript, so check the pin there as well
+ World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
+
+ if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
+ m_host.Inventory.RemoveInventoryItem(item.ItemID);
+ }
+ }
+ // this will cause the delay even if the script pin or permissions were wrong - seems ok
+ ScriptSleep(m_sleepMsOnRemoteLoadScriptPin);
}
public void llOpenRemoteDataChannel()
@@ -7432,12 +8150,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj,
new DetectParams[0]));
}
+ ScriptSleep(m_sleepMsOnOpenRemoteDataChannel);
}
public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
{
m_host.AddScriptLPS(1);
IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface();
+ ScriptSleep(m_sleepMsOnSendRemoteData);
if (xmlrpcMod == null)
return "";
return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString();
@@ -7449,6 +8169,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface();
if (xmlrpcMod != null)
xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
+ ScriptSleep(m_sleepMsOnRemoteDataReply);
}
public void llCloseRemoteDataChannel(string channel)
@@ -7464,24 +8185,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface();
if (xmlrpcMod != null)
xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
+ ScriptSleep(m_sleepMsOnCloseRemoteDataChannel);
}
public LSL_String llMD5String(string src, int nonce)
{
m_host.AddScriptLPS(1);
- return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()));
+ return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
}
public LSL_String llSHA1String(string src)
{
m_host.AddScriptLPS(1);
- return Util.SHA1Hash(src).ToLower();
+ return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
}
protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
{
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return shapeBlock;
if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -7586,6 +8310,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Prim type box, cylinder and prism.
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)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock;
@@ -7639,6 +8366,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Prim type sphere.
protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
ObjectShapePacket.ObjectDataBlock shapeBlock;
shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7685,6 +8415,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Prim type torus, tube and ring.
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)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock;
@@ -7820,6 +8553,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// Prim type sculpt.
protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
{
+ if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
+ return;
+
ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
UUID sculptId;
@@ -7842,7 +8578,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
{
// default
- type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
+ type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
}
part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7855,6 +8591,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
+
+ ScriptSleep(m_sleepMsOnSetPrimitiveParams);
}
public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
@@ -7862,6 +8600,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
+
+ ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams);
}
public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
@@ -7871,9 +8611,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
}
- protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
+ private void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
{
- SetEntityParams(GetLinkEntities(linknumber), rules, originFunc);
+ List