2008-05-30 12:27:06 +00:00
/ *
* 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 .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-05-30 12:27:06 +00:00
* 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 .
* /
2010-09-24 14:26:53 +00:00
2008-05-30 12:27:06 +00:00
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Runtime.Remoting.Lifetime ;
using System.Text ;
using System.Threading ;
2009-07-18 20:10:19 +00:00
using System.Text.RegularExpressions ;
2008-06-07 17:43:07 +00:00
using Nini.Config ;
2009-02-22 01:26:18 +00:00
using log4net ;
2008-09-06 07:52:41 +00:00
using OpenMetaverse ;
using OpenMetaverse.Packets ;
2008-06-07 17:43:07 +00:00
using OpenSim ;
2008-05-30 12:27:06 +00:00
using OpenSim.Framework ;
2010-01-11 15:51:33 +00:00
2009-02-10 13:10:57 +00:00
using OpenSim.Region.CoreModules ;
using OpenSim.Region.CoreModules.World.Land ;
using OpenSim.Region.CoreModules.World.Terrain ;
2009-11-17 15:20:02 +00:00
using OpenSim.Region.Framework.Interfaces ;
2009-02-06 16:55:34 +00:00
using OpenSim.Region.Framework.Scenes ;
2009-11-17 15:20:02 +00:00
using OpenSim.Region.Framework.Scenes.Animation ;
2008-07-24 07:45:58 +00:00
using OpenSim.Region.Physics.Manager ;
2008-06-24 21:09:49 +00:00
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 ;
2009-09-26 14:48:21 +00:00
using OpenSim.Services.Interfaces ;
using GridRegion = OpenSim . Services . Interfaces . GridRegion ;
2010-01-08 18:43:34 +00:00
using PresenceInfo = OpenSim . Services . Interfaces . PresenceInfo ;
2010-02-08 15:53:20 +00:00
using PrimType = OpenSim . Region . Framework . Scenes . PrimType ;
2009-07-25 15:49:10 +00:00
using AssetLandmark = OpenSim . Framework . AssetLandmark ;
2008-09-23 11:41:34 +00:00
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 ;
2009-02-22 20:52:55 +00:00
using System.Reflection ;
2008-09-23 11:41:34 +00:00
2008-06-24 21:09:49 +00:00
namespace OpenSim.Region.ScriptEngine.Shared.Api
2008-05-30 12:27:06 +00:00
{
2010-08-05 20:50:09 +00:00
// MUST be a ref type
public class UserInfoCacheEntry
{
public int time ;
public UserAccount account ;
public PresenceInfo pinfo ;
}
2008-05-30 12:27:06 +00:00
/// <summary>
/// Contains all LSL ll-functions. This class will be in Default AppDomain.
/// </summary>
2008-11-26 14:23:46 +00:00
public class LSL_Api : MarshalByRefObject , ILSL_Api , IScriptApi
2008-05-30 12:27:06 +00:00
{
2011-04-01 04:14:53 +00:00
private static readonly ILog m_log = LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2008-11-08 02:24:34 +00:00
protected IScriptEngine m_ScriptEngine ;
2008-09-26 02:51:00 +00:00
protected SceneObjectPart m_host ;
2012-04-23 21:23:47 +00:00
/// <summary>
2012-05-08 21:58:34 +00:00
/// The item that hosts this script
2012-04-23 21:23:47 +00:00
/// </summary>
2012-05-08 21:58:34 +00:00
protected TaskInventoryItem m_item ;
2012-04-23 21:23:47 +00:00
2008-09-26 02:51:00 +00:00
protected bool throwErrorOnNotImplemented = true ;
protected AsyncCommandManager AsyncCommands = null ;
protected float m_ScriptDelayFactor = 1.0f ;
protected float m_ScriptDistanceFactor = 1.0f ;
2008-11-10 05:33:36 +00:00
protected float m_MinTimerInterval = 0.5f ;
2008-09-26 02:51:00 +00:00
2009-07-06 13:09:03 +00:00
protected DateTime m_timer = DateTime . Now ;
2009-09-16 14:33:42 +00:00
protected bool m_waitingForScriptAnswer = false ;
protected bool m_automaticLinkPermission = false ;
2009-07-06 13:09:03 +00:00
protected IMessageTransferModule m_TransferModule = null ;
protected int m_notecardLineReadCharsMax = 255 ;
2009-09-16 14:33:42 +00:00
protected int m_scriptConsoleChannel = 0 ;
protected bool m_scriptConsoleChannelEnabled = false ;
2009-07-06 13:09:03 +00:00
protected IUrlModule m_UrlModule = null ;
2012-05-25 23:36:01 +00:00
protected Dictionary < UUID , UserInfoCacheEntry > m_userInfoCache = new Dictionary < UUID , UserInfoCacheEntry > ( ) ;
protected int EMAIL_PAUSE_TIME = 20 ; // documented delay value for smtp.
2008-05-30 12:27:06 +00:00
2012-05-08 22:20:27 +00:00
public void Initialize ( IScriptEngine ScriptEngine , SceneObjectPart host , TaskInventoryItem item )
2008-05-30 12:27:06 +00:00
{
m_ScriptEngine = ScriptEngine ;
m_host = host ;
2012-05-08 21:58:34 +00:00
m_item = item ;
2008-05-30 12:27:06 +00:00
2012-05-13 20:58:47 +00:00
LoadLimits ( ) ; // read script limits from config.
m_TransferModule =
m_ScriptEngine . World . RequestModuleInterface < IMessageTransferModule > ( ) ;
m_UrlModule = m_ScriptEngine . World . RequestModuleInterface < IUrlModule > ( ) ;
AsyncCommands = new AsyncCommandManager ( ScriptEngine ) ;
}
/* load configuration items that affect script, object and run-time behavior. */
private void LoadLimits ( )
{
2009-09-30 16:51:02 +00:00
m_ScriptDelayFactor =
m_ScriptEngine . Config . GetFloat ( "ScriptDelayFactor" , 1.0f ) ;
m_ScriptDistanceFactor =
m_ScriptEngine . Config . GetFloat ( "ScriptDistanceLimitFactor" , 1.0f ) ;
m_MinTimerInterval =
m_ScriptEngine . Config . GetFloat ( "MinTimerInterval" , 0.5f ) ;
m_automaticLinkPermission =
m_ScriptEngine . Config . GetBoolean ( "AutomaticLinkPermission" , false ) ;
m_notecardLineReadCharsMax =
m_ScriptEngine . Config . GetInt ( "NotecardLineReadCharsMax" , 255 ) ;
2009-03-17 07:03:53 +00:00
if ( m_notecardLineReadCharsMax > 65535 )
m_notecardLineReadCharsMax = 65535 ;
2012-05-13 20:58:47 +00:00
// load limits for particular subsystems.
IConfig SMTPConfig ;
if ( ( SMTPConfig = m_ScriptEngine . ConfigSource . Configs [ "SMTP" ] ) ! = null ) {
// there's an smtp config, so load in the snooze time.
EMAIL_PAUSE_TIME = SMTPConfig . GetInt ( "email_pause_time" , EMAIL_PAUSE_TIME ) ;
}
2008-05-30 12:27:06 +00:00
}
2008-11-29 11:20:06 +00:00
public override Object InitializeLifetimeService ( )
{
ILease lease = ( ILease ) base . InitializeLifetimeService ( ) ;
2008-05-30 12:27:06 +00:00
2008-11-29 11:20:06 +00:00
if ( lease . CurrentState = = LeaseState . Initial )
{
2009-08-14 13:18:56 +00:00
lease . InitialLeaseTime = TimeSpan . FromMinutes ( 0 ) ;
// lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
// lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
2008-11-29 11:20:06 +00:00
}
return lease ;
}
2008-05-30 12:27:06 +00:00
2009-07-06 13:09:03 +00:00
protected virtual void ScriptSleep ( int delay )
2008-09-26 02:51:00 +00:00
{
delay = ( int ) ( ( float ) delay * m_ScriptDelayFactor ) ;
if ( delay = = 0 )
return ;
System . Threading . Thread . Sleep ( delay ) ;
}
public Scene World
2008-06-24 21:09:49 +00:00
{
2008-09-26 02:51:00 +00:00
get { return m_ScriptEngine . World ; }
2008-06-24 21:09:49 +00:00
}
2008-09-26 02:51:00 +00:00
public void state ( string newState )
{
2012-05-08 21:58:34 +00:00
m_ScriptEngine . SetState ( m_item . ItemID , newState ) ;
2008-09-26 02:51:00 +00:00
}
2008-09-29 20:24:59 +00:00
/// <summary>
/// Reset the named script. The script must be present
/// in the same prim.
/// </summary>
2008-09-26 02:51:00 +00:00
public void llResetScript ( )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-07 19:48:22 +00:00
// We need to tell the URL module, if we hav one, to release
// the allocated URLs
if ( m_UrlModule ! = null )
m_UrlModule . ScriptRemoved ( m_item . ItemID ) ;
2012-05-08 21:58:34 +00:00
m_ScriptEngine . ApiResetScript ( m_item . ItemID ) ;
2008-09-26 02:51:00 +00:00
}
public void llResetOtherScript ( string name )
{
UUID item ;
m_host . AddScriptLPS ( 1 ) ;
2012-07-04 20:54:30 +00:00
if ( ( item = GetScriptByName ( name ) ) ! = UUID . Zero )
2008-09-26 02:51:00 +00:00
m_ScriptEngine . ResetScript ( item ) ;
else
ShoutError ( "llResetOtherScript: script " + name + " not found" ) ;
}
2008-09-25 06:04:47 +00:00
public LSL_Integer llGetScriptState ( string name )
2008-05-30 12:27:06 +00:00
{
2008-09-25 06:04:47 +00:00
UUID item ;
2008-05-30 12:27:06 +00:00
m_host . AddScriptLPS ( 1 ) ;
2012-07-04 20:54:30 +00:00
if ( ( item = GetScriptByName ( name ) ) ! = UUID . Zero )
2008-05-30 12:27:06 +00:00
{
2008-09-26 02:51:00 +00:00
return m_ScriptEngine . GetScriptState ( item ) ? 1 : 0 ;
2008-05-30 12:27:06 +00:00
}
2008-09-25 06:04:47 +00:00
ShoutError ( "llGetScriptState: script " + name + " not found" ) ;
2008-05-30 12:27:06 +00:00
2008-09-25 06:04:47 +00:00
// If we didn't find it, then it's safe to
// assume it is not running.
2008-05-30 12:27:06 +00:00
2008-09-25 06:04:47 +00:00
return 0 ;
2008-05-30 12:27:06 +00:00
}
2008-09-26 02:51:00 +00:00
public void llSetScriptState ( string name , int run )
2008-05-30 12:27:06 +00:00
{
2008-09-25 06:04:47 +00:00
UUID item ;
2008-05-30 12:27:06 +00:00
m_host . AddScriptLPS ( 1 ) ;
2008-09-26 02:51:00 +00:00
// These functions are supposed to be robust,
// so get the state one step at a time.
2012-07-04 20:54:30 +00:00
if ( ( item = GetScriptByName ( name ) ) ! = UUID . Zero )
2008-09-26 02:51:00 +00:00
{
m_ScriptEngine . SetScriptState ( item , run = = 0 ? false : true ) ;
}
2008-05-30 12:27:06 +00:00
else
2008-09-26 02:51:00 +00:00
{
ShoutError ( "llSetScriptState: script " + name + " not found" ) ;
}
2008-05-30 12:27:06 +00:00
}
2009-08-07 20:51:03 +00:00
public List < SceneObjectPart > GetLinkParts ( int linkType )
2012-08-15 20:14:39 +00:00
{
return GetLinkParts ( m_host , linkType ) ;
}
private List < SceneObjectPart > GetLinkParts ( SceneObjectPart part , int linkType )
2008-09-26 02:51:00 +00:00
{
List < SceneObjectPart > ret = new List < SceneObjectPart > ( ) ;
2012-08-15 20:14:39 +00:00
ret . Add ( part ) ;
2008-09-26 02:51:00 +00:00
switch ( linkType )
{
case ScriptBaseClass . LINK_SET :
2012-08-15 20:14:39 +00:00
return new List < SceneObjectPart > ( part . ParentGroup . Parts ) ;
2008-09-26 02:51:00 +00:00
case ScriptBaseClass . LINK_ROOT :
2011-09-01 00:22:28 +00:00
ret = new List < SceneObjectPart > ( ) ;
2012-08-15 20:14:39 +00:00
ret . Add ( part . ParentGroup . RootPart ) ;
2008-09-26 02:51:00 +00:00
return ret ;
case ScriptBaseClass . LINK_ALL_OTHERS :
2012-08-15 20:14:39 +00:00
ret = new List < SceneObjectPart > ( part . ParentGroup . Parts ) ;
2010-09-24 14:26:53 +00:00
2012-08-15 20:14:39 +00:00
if ( ret . Contains ( part ) )
ret . Remove ( part ) ;
2011-09-01 00:22:28 +00:00
2008-09-26 02:51:00 +00:00
return ret ;
case ScriptBaseClass . LINK_ALL_CHILDREN :
2012-08-15 20:14:39 +00:00
ret = new List < SceneObjectPart > ( part . ParentGroup . Parts ) ;
2010-09-24 14:26:53 +00:00
2012-08-15 20:14:39 +00:00
if ( ret . Contains ( part . ParentGroup . RootPart ) )
ret . Remove ( part . ParentGroup . RootPart ) ;
2008-09-26 02:51:00 +00:00
return ret ;
case ScriptBaseClass . LINK_THIS :
return ret ;
default :
2011-09-01 00:22:28 +00:00
if ( linkType < 0 )
2008-09-26 02:51:00 +00:00
return new List < SceneObjectPart > ( ) ;
2011-09-01 00:22:28 +00:00
2012-08-15 20:14:39 +00:00
SceneObjectPart target = part . ParentGroup . GetLinkNumPart ( linkType ) ;
2008-09-26 02:51:00 +00:00
if ( target = = null )
return new List < SceneObjectPart > ( ) ;
ret = new List < SceneObjectPart > ( ) ;
ret . Add ( target ) ;
return ret ;
}
}
2009-07-06 13:09:03 +00:00
protected UUID InventoryKey ( string name , int type )
2008-05-30 12:27:06 +00:00
{
2012-05-26 00:03:53 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( name ) ;
2009-02-20 14:04:29 +00:00
2012-05-26 00:03:53 +00:00
if ( item ! = null & & item . Type = = type )
return item . AssetID ;
else
return UUID . Zero ;
2008-05-30 12:27:06 +00:00
}
2008-09-26 02:51:00 +00:00
/// <summary>
/// accepts a valid UUID, -or- a name of an inventory item.
/// Returns a valid UUID or UUID.Zero if key invalid and item not found
/// in prim inventory.
/// </summary>
/// <param name="k"></param>
/// <returns></returns>
2009-07-06 13:09:03 +00:00
protected UUID KeyOrName ( string k )
2008-09-26 02:51:00 +00:00
{
2012-05-25 23:36:01 +00:00
UUID key ;
2008-09-26 02:51:00 +00:00
// if we can parse the string as a key, use it.
// else try to locate the name in inventory of object. found returns key,
2012-05-25 23:36:01 +00:00
// not found returns UUID.Zero
if ( ! UUID . TryParse ( k , out key ) )
2008-09-26 02:51:00 +00:00
{
2012-05-25 23:36:01 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( k ) ;
if ( item ! = null )
key = item . AssetID ;
else
key = UUID . Zero ;
2008-09-26 02:51:00 +00:00
}
2012-05-25 23:36:01 +00:00
return key ;
2008-09-26 02:51:00 +00:00
}
2008-05-30 12:27:06 +00:00
2008-09-26 02:51:00 +00:00
//These are the implementations of the various ll-functions used by the LSL scripts.
public LSL_Float llSin ( double f )
{
2008-05-30 12:27:06 +00:00
m_host . AddScriptLPS ( 1 ) ;
2008-09-26 02:51:00 +00:00
return ( double ) Math . Sin ( f ) ;
}
2008-05-30 12:27:06 +00:00
2008-09-26 02:51:00 +00:00
public LSL_Float llCos ( double f )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Cos ( f ) ;
}
2008-05-30 12:27:06 +00:00
2008-09-26 02:51:00 +00:00
public LSL_Float llTan ( double f )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Tan ( f ) ;
}
public LSL_Float llAtan2 ( double x , double y )
{
m_host . AddScriptLPS ( 1 ) ;
2009-02-07 13:16:27 +00:00
return ( double ) Math . Atan2 ( x , y ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Float llSqrt ( double f )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Sqrt ( f ) ;
}
public LSL_Float llPow ( double fbase , double fexponent )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Pow ( fbase , fexponent ) ;
}
public LSL_Integer llAbs ( int i )
{
2009-02-13 02:52:08 +00:00
// changed to replicate LSL behaviour whereby minimum int value is returned untouched.
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
2009-02-13 02:52:08 +00:00
if ( i = = Int32 . MinValue )
return i ;
2009-02-10 13:36:42 +00:00
else
2009-02-13 02:52:08 +00:00
return ( int ) Math . Abs ( i ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Float llFabs ( double f )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Abs ( f ) ;
}
public LSL_Float llFrand ( double mag )
{
m_host . AddScriptLPS ( 1 ) ;
lock ( Util . RandomClass )
2008-05-30 12:27:06 +00:00
{
2008-09-26 02:51:00 +00:00
return Util . RandomClass . NextDouble ( ) * mag ;
2008-05-30 12:27:06 +00:00
}
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llFloor ( double f )
{
m_host . AddScriptLPS ( 1 ) ;
return ( int ) Math . Floor ( f ) ;
}
public LSL_Integer llCeil ( double f )
{
m_host . AddScriptLPS ( 1 ) ;
return ( int ) Math . Ceiling ( f ) ;
}
// Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
public LSL_Integer llRound ( double f )
{
m_host . AddScriptLPS ( 1 ) ;
return ( int ) Math . Round ( f , MidpointRounding . AwayFromZero ) ;
}
//This next group are vector operations involving squaring and square root. ckrinke
public LSL_Float llVecMag ( LSL_Vector v )
{
m_host . AddScriptLPS ( 1 ) ;
return LSL_Vector . Mag ( v ) ;
}
public LSL_Vector llVecNorm ( LSL_Vector v )
{
2010-07-08 23:05:59 +00:00
m_host . AddScriptLPS ( 1 ) ;
2010-07-08 17:06:08 +00:00
return LSL_Vector . Norm ( v ) ;
2008-09-26 02:51:00 +00:00
}
2012-07-14 00:41:51 +00:00
private double VecDist ( LSL_Vector a , LSL_Vector b )
2008-09-26 02:51:00 +00:00
{
double dx = a . x - b . x ;
double dy = a . y - b . y ;
double dz = a . z - b . z ;
return Math . Sqrt ( dx * dx + dy * dy + dz * dz ) ;
}
2012-07-14 00:14:00 +00:00
public LSL_Float llVecDist ( LSL_Vector a , LSL_Vector b )
{
m_host . AddScriptLPS ( 1 ) ;
2012-07-14 00:41:51 +00:00
return VecDist ( a , b ) ;
2012-07-14 00:14:00 +00:00
}
2008-09-26 02:51:00 +00:00
//Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
2012-01-06 21:12:22 +00:00
/// <summary>
/// Convert an LSL rotation to a Euler vector.
/// </summary>
/// <remarks>
/// 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
/// </remarks>
/// <param name="r"></param>
/// <returns></returns>
2008-09-26 02:51:00 +00:00
public LSL_Vector llRot2Euler ( LSL_Rotation r )
{
2012-01-06 21:12:22 +00:00
m_host . AddScriptLPS ( 1 ) ;
2012-01-03 17:38:38 +00:00
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 ) ;
2012-01-06 21:12:22 +00:00
2012-01-03 17:38:38 +00:00
return new LSL_Vector ( x , y , z ) ;
2008-09-26 02:51:00 +00:00
}
/ * From wiki :
The Euler angle vector ( in radians ) is converted to a rotation by doing the rotations around the 3 axes
in Z , Y , X order . So llEuler2Rot ( < 1.0 , 2.0 , 3.0 > * DEG_TO_RAD ) generates a rotation by taking the zero rotation ,
a vector pointing along the X axis , first rotating it 3 degrees around the global Z axis , then rotating the resulting
vector 2 degrees around the global Y axis , and finally rotating that 1 degree around the global X axis .
* /
/ * How we arrived at this llEuler2Rot
*
* Experiment in SL to determine conventions :
* llEuler2Rot ( < PI , 0 , 0 > ) = < 1 , 0 , 0 , 0 >
* llEuler2Rot ( < 0 , PI , 0 > ) = < 0 , 1 , 0 , 0 >
* llEuler2Rot ( < 0 , 0 , PI > ) = < 0 , 0 , 1 , 0 >
*
* Important facts about Quaternions
* - multiplication is non - commutative ( a * b ! = b * a )
* - http : //en.wikipedia.org/wiki/Quaternion#Basis_multiplication
*
* Above SL experiment gives ( c1 , c2 , c3 , s1 , s2 , s3 as defined in our llEuler2Rot ) :
* Qx = c1 + i * s1
* Qy = c2 + j * s2 ;
* Qz = c3 + k * s3 ;
*
* Rotations applied in order ( from above ) Z , Y , X
* Q = ( Qz * Qy ) * Qx
* ( ( c1 + i * s1 ) * ( c2 + j * s2 ) ) * ( c3 + k * s3 )
* ( c1 * c2 + i * s1 * c2 + j * c1 * s2 + ij * s1 * s2 ) * ( c3 + k * s3 )
* ( c1 * c2 + i * s1 * c2 + j * c1 * s2 + k * s1 * s2 ) * ( c3 + k * s3 )
* c1 * c2 * c3 + i * s1 * c2 * c3 + j * c1 * s2 * c3 + k * s1 * s2 * c3 + k * c1 * c2 * s3 + ik * s1 * c2 * s3 + jk * c1 * s2 * s3 + kk * s1 * s2 * s3
* c1 * c2 * c3 + i * s1 * c2 * c3 + j * c1 * s2 * c3 + k * s1 * s2 * c3 + k * c1 * c2 * s3 - j * s1 * c2 * s3 + i * c1 * s2 * s3 - s1 * s2 * s3
* regroup : x = i * ( s1 * c2 * c3 + c1 * s2 * s3 )
* y = j * ( c1 * s2 * c3 - s1 * c2 * s3 )
* z = k * ( s1 * s2 * c3 + c1 * c2 * s3 )
* s = c1 * c2 * c3 - s1 * s2 * s3
*
* This implementation agrees with the functions found here :
* http : //lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
* And with the results in SL .
*
* It ' s also possible to calculate llEuler2Rot by direct multiplication of
* the Qz , Qy , and Qx vectors ( as above - and done in the "accurate" function
* from the wiki ) .
* Apparently in some cases this is better from a numerical precision perspective ?
* /
public LSL_Rotation llEuler2Rot ( LSL_Vector v )
{
m_host . AddScriptLPS ( 1 ) ;
double x , y , z , s ;
2009-09-08 00:12:17 +00:00
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 ) ;
2008-09-26 02:51:00 +00:00
2009-09-16 14:33:42 +00:00
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 ;
2008-09-26 02:51:00 +00:00
return new LSL_Rotation ( x , y , z , s ) ;
}
public LSL_Rotation llAxes2Rot ( LSL_Vector fwd , LSL_Vector left , LSL_Vector up )
{
m_host . AddScriptLPS ( 1 ) ;
2008-12-22 03:08:39 +00:00
double s ;
double tr = fwd . x + left . y + up . z + 1.0 ;
if ( tr > = 1.0 )
{
s = 0.5 / Math . Sqrt ( tr ) ;
return new LSL_Rotation (
( left . z - up . y ) * s ,
( up . x - fwd . z ) * s ,
( fwd . y - left . x ) * s ,
0.25 / s ) ;
}
else
{
double max = ( left . y > up . z ) ? left . y : up . z ;
if ( max < fwd . x )
{
s = Math . Sqrt ( fwd . x - ( left . y + up . z ) + 1.0 ) ;
double x = s * 0.5 ;
s = 0.5 / s ;
return new LSL_Rotation (
x ,
( fwd . y + left . x ) * s ,
( up . x + fwd . z ) * s ,
( left . z - up . y ) * s ) ;
}
else if ( max = = left . y )
{
s = Math . Sqrt ( left . y - ( up . z + fwd . x ) + 1.0 ) ;
double y = s * 0.5 ;
s = 0.5 / s ;
return new LSL_Rotation (
( fwd . y + left . x ) * s ,
y ,
( left . z + up . y ) * s ,
( up . x - fwd . z ) * s ) ;
}
else
{
s = Math . Sqrt ( up . z - ( fwd . x + left . y ) + 1.0 ) ;
double z = s * 0.5 ;
s = 0.5 / s ;
return new LSL_Rotation (
( up . x + fwd . z ) * s ,
( left . z + up . y ) * s ,
z ,
( fwd . y - left . x ) * s ) ;
}
}
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llRot2Fwd ( LSL_Rotation r )
{
m_host . AddScriptLPS ( 1 ) ;
double x , y , z , m ;
m = r . x * r . x + r . y * r . y + r . z * r . z + r . s * r . s ;
// m is always greater than zero
// if m is not equal to 1 then Rotation needs to be normalized
if ( Math . Abs ( 1.0 - m ) > 0.000001 ) // allow a little slop here for calculation precision
2008-05-30 12:27:06 +00:00
{
2008-09-26 02:51:00 +00:00
m = 1.0 / Math . Sqrt ( m ) ;
r . x * = m ;
r . y * = m ;
r . z * = m ;
r . s * = m ;
}
// Fast Algebric Calculations instead of Vectors & Quaternions Product
x = r . x * r . x - r . y * r . y - r . z * r . z + r . s * r . s ;
y = 2 * ( r . x * r . y + r . z * r . s ) ;
z = 2 * ( r . x * r . z - r . y * r . s ) ;
return ( new LSL_Vector ( x , y , z ) ) ;
}
public LSL_Vector llRot2Left ( LSL_Rotation r )
{
m_host . AddScriptLPS ( 1 ) ;
double x , y , z , m ;
m = r . x * r . x + r . y * r . y + r . z * r . z + r . s * r . s ;
// m is always greater than zero
// if m is not equal to 1 then Rotation needs to be normalized
if ( Math . Abs ( 1.0 - m ) > 0.000001 ) // allow a little slop here for calculation precision
{
m = 1.0 / Math . Sqrt ( m ) ;
r . x * = m ;
r . y * = m ;
r . z * = m ;
r . s * = m ;
}
// Fast Algebric Calculations instead of Vectors & Quaternions Product
x = 2 * ( r . x * r . y - r . z * r . s ) ;
y = - r . x * r . x + r . y * r . y - r . z * r . z + r . s * r . s ;
z = 2 * ( r . x * r . s + r . y * r . z ) ;
return ( new LSL_Vector ( x , y , z ) ) ;
}
public LSL_Vector llRot2Up ( LSL_Rotation r )
{
m_host . AddScriptLPS ( 1 ) ;
double x , y , z , m ;
m = r . x * r . x + r . y * r . y + r . z * r . z + r . s * r . s ;
// m is always greater than zero
// if m is not equal to 1 then Rotation needs to be normalized
if ( Math . Abs ( 1.0 - m ) > 0.000001 ) // allow a little slop here for calculation precision
{
m = 1.0 / Math . Sqrt ( m ) ;
r . x * = m ;
r . y * = m ;
r . z * = m ;
r . s * = m ;
}
// Fast Algebric Calculations instead of Vectors & Quaternions Product
x = 2 * ( r . x * r . z + r . y * r . s ) ;
y = 2 * ( - r . x * r . s + r . y * r . z ) ;
z = - r . x * r . x - r . y * r . y + r . z * r . z + r . s * r . s ;
return ( new LSL_Vector ( x , y , z ) ) ;
}
public LSL_Rotation llRotBetween ( LSL_Vector a , LSL_Vector b )
{
2010-06-29 13:25:12 +00:00
//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 ) )
{
rotBetween = new LSL_Rotation ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
}
else
{
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 ) ;
}
}
}
2010-06-29 00:33:47 +00:00
return rotBetween ;
2008-09-26 02:51:00 +00:00
}
public void llWhisper ( int channelID , string text )
{
m_host . AddScriptLPS ( 1 ) ;
if ( text . Length > 1023 )
text = text . Substring ( 0 , 1023 ) ;
World . SimChat ( Utils . StringToBytes ( text ) ,
2008-11-17 05:57:58 +00:00
ChatTypeEnum . Whisper , channelID , m_host . ParentGroup . RootPart . AbsolutePosition , m_host . Name , m_host . UUID , false ) ;
2008-09-26 02:51:00 +00:00
IWorldComm wComm = m_ScriptEngine . World . RequestModuleInterface < IWorldComm > ( ) ;
2009-11-28 09:23:26 +00:00
if ( wComm ! = null )
wComm . DeliverMessage ( ChatTypeEnum . Whisper , channelID , m_host . Name , m_host . UUID , text ) ;
2008-09-26 02:51:00 +00:00
}
public void llSay ( int channelID , string text )
{
m_host . AddScriptLPS ( 1 ) ;
2009-09-16 14:33:42 +00:00
if ( m_scriptConsoleChannelEnabled & & ( channelID = = m_scriptConsoleChannel ) )
{
Console . WriteLine ( text ) ;
}
else
{
if ( text . Length > 1023 )
text = text . Substring ( 0 , 1023 ) ;
2008-09-26 02:51:00 +00:00
2009-09-16 14:33:42 +00:00
World . SimChat ( Utils . StringToBytes ( text ) ,
ChatTypeEnum . Say , channelID , m_host . ParentGroup . RootPart . AbsolutePosition , m_host . Name , m_host . UUID , false ) ;
2008-09-26 02:51:00 +00:00
2009-09-16 14:33:42 +00:00
IWorldComm wComm = m_ScriptEngine . World . RequestModuleInterface < IWorldComm > ( ) ;
2009-11-28 09:23:26 +00:00
if ( wComm ! = null )
wComm . DeliverMessage ( ChatTypeEnum . Say , channelID , m_host . Name , m_host . UUID , text ) ;
2009-09-16 14:33:42 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llShout ( int channelID , string text )
{
m_host . AddScriptLPS ( 1 ) ;
if ( text . Length > 1023 )
text = text . Substring ( 0 , 1023 ) ;
World . SimChat ( Utils . StringToBytes ( text ) ,
2008-11-17 05:57:58 +00:00
ChatTypeEnum . Shout , channelID , m_host . ParentGroup . RootPart . AbsolutePosition , m_host . Name , m_host . UUID , true ) ;
2008-09-26 02:51:00 +00:00
IWorldComm wComm = m_ScriptEngine . World . RequestModuleInterface < IWorldComm > ( ) ;
2009-11-28 09:23:26 +00:00
if ( wComm ! = null )
wComm . DeliverMessage ( ChatTypeEnum . Shout , channelID , m_host . Name , m_host . UUID , text ) ;
2008-09-26 02:51:00 +00:00
}
public void llRegionSay ( int channelID , string text )
{
if ( channelID = = 0 )
{
LSLError ( "Cannot use llRegionSay() on channel 0" ) ;
return ;
}
if ( text . Length > 1023 )
text = text . Substring ( 0 , 1023 ) ;
m_host . AddScriptLPS ( 1 ) ;
IWorldComm wComm = m_ScriptEngine . World . RequestModuleInterface < IWorldComm > ( ) ;
2009-11-28 09:23:26 +00:00
if ( wComm ! = null )
wComm . DeliverMessage ( ChatTypeEnum . Region , channelID , m_host . Name , m_host . UUID , text ) ;
2008-09-26 02:51:00 +00:00
}
2011-08-19 22:47:21 +00:00
public void llRegionSayTo ( string target , int channel , string msg )
{
if ( msg . Length > 1023 )
msg = msg . Substring ( 0 , 1023 ) ;
m_host . AddScriptLPS ( 1 ) ;
2012-04-22 22:07:50 +00:00
if ( channel = = ScriptBaseClass . DEBUG_CHANNEL )
{
return ;
}
2011-08-19 22:47:21 +00:00
UUID TargetID ;
UUID . TryParse ( target , out TargetID ) ;
IWorldComm wComm = m_ScriptEngine . World . RequestModuleInterface < IWorldComm > ( ) ;
if ( wComm ! = null )
2012-04-22 22:07:50 +00:00
wComm . DeliverMessageTo ( TargetID , channel , m_host . AbsolutePosition , m_host . Name , m_host . UUID , msg ) ;
2011-08-19 22:47:21 +00:00
}
2008-09-26 02:51:00 +00:00
public LSL_Integer llListen ( int channelID , string name , string ID , string msg )
{
m_host . AddScriptLPS ( 1 ) ;
UUID keyID ;
UUID . TryParse ( ID , out keyID ) ;
IWorldComm wComm = m_ScriptEngine . World . RequestModuleInterface < IWorldComm > ( ) ;
2009-11-28 09:23:26 +00:00
if ( wComm ! = null )
2012-05-08 22:20:27 +00:00
return wComm . Listen ( m_host . LocalId , m_item . ItemID , m_host . UUID , channelID , name , keyID , msg ) ;
2009-11-28 09:23:26 +00:00
else
return - 1 ;
2008-09-26 02:51:00 +00:00
}
public void llListenControl ( int number , int active )
{
m_host . AddScriptLPS ( 1 ) ;
IWorldComm wComm = m_ScriptEngine . World . RequestModuleInterface < IWorldComm > ( ) ;
2009-11-28 09:23:26 +00:00
if ( wComm ! = null )
2012-05-08 21:58:34 +00:00
wComm . ListenControl ( m_item . ItemID , number , active ) ;
2008-09-26 02:51:00 +00:00
}
public void llListenRemove ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
IWorldComm wComm = m_ScriptEngine . World . RequestModuleInterface < IWorldComm > ( ) ;
2009-11-28 09:23:26 +00:00
if ( wComm ! = null )
2012-05-08 21:58:34 +00:00
wComm . ListenRemove ( m_item . ItemID , number ) ;
2008-09-26 02:51:00 +00:00
}
public void llSensor ( string name , string id , int type , double range , double arc )
{
m_host . AddScriptLPS ( 1 ) ;
UUID keyID = UUID . Zero ;
UUID . TryParse ( id , out keyID ) ;
2012-05-08 22:20:27 +00:00
AsyncCommands . SensorRepeatPlugin . SenseOnce ( m_host . LocalId , m_item . ItemID , name , keyID , type , range , arc , m_host ) ;
2008-09-26 02:51:00 +00:00
}
public void llSensorRepeat ( string name , string id , int type , double range , double arc , double rate )
{
m_host . AddScriptLPS ( 1 ) ;
UUID keyID = UUID . Zero ;
UUID . TryParse ( id , out keyID ) ;
2012-05-08 22:20:27 +00:00
AsyncCommands . SensorRepeatPlugin . SetSenseRepeatEvent ( m_host . LocalId , m_item . ItemID , name , keyID , type , range , arc , rate , m_host ) ;
2008-09-26 02:51:00 +00:00
}
public void llSensorRemove ( )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 22:20:27 +00:00
AsyncCommands . SensorRepeatPlugin . UnSetSenseRepeaterEvents ( m_host . LocalId , m_item . ItemID ) ;
2008-09-26 02:51:00 +00:00
}
public string resolveName ( UUID objecUUID )
{
// try avatar username surname
2010-01-10 18:40:07 +00:00
UserAccount account = World . UserAccountService . GetUserAccount ( World . RegionInfo . ScopeID , objecUUID ) ;
if ( account ! = null )
2008-09-26 02:51:00 +00:00
{
2010-01-10 18:40:07 +00:00
string avatarname = account . Name ;
2008-09-26 02:51:00 +00:00
return avatarname ;
}
// try an scene object
SceneObjectPart SOP = World . GetSceneObjectPart ( objecUUID ) ;
if ( SOP ! = null )
{
string objectname = SOP . Name ;
return objectname ;
}
EntityBase SensedObject ;
2008-11-24 15:14:33 +00:00
World . Entities . TryGetValue ( objecUUID , out SensedObject ) ;
2008-09-26 02:51:00 +00:00
if ( SensedObject = = null )
2009-10-14 16:39:38 +00:00
{
IGroupsModule groups = World . RequestModuleInterface < IGroupsModule > ( ) ;
if ( groups ! = null )
{
GroupRecord gr = groups . GetGroupRecord ( objecUUID ) ;
if ( gr ! = null )
return gr . GroupName ;
}
2008-09-26 02:51:00 +00:00
return String . Empty ;
2009-10-14 16:39:38 +00:00
}
2008-09-26 02:51:00 +00:00
return SensedObject . Name ;
}
public LSL_String llDetectedName ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null )
2008-09-26 02:51:00 +00:00
return String . Empty ;
2008-11-08 23:55:40 +00:00
return detectedParams . Name ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llDetectedKey ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null )
2008-09-26 02:51:00 +00:00
return String . Empty ;
2008-11-08 23:55:40 +00:00
return detectedParams . Key . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llDetectedOwner ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null )
2008-09-26 02:51:00 +00:00
return String . Empty ;
2008-11-08 23:55:40 +00:00
return detectedParams . Owner . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llDetectedType ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null )
2008-09-26 02:51:00 +00:00
return 0 ;
2008-11-08 23:55:40 +00:00
return new LSL_Integer ( detectedParams . Type ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llDetectedPos ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null )
2008-09-26 02:51:00 +00:00
return new LSL_Vector ( ) ;
2008-11-08 23:55:40 +00:00
return detectedParams . Position ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llDetectedVel ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null )
2008-09-26 02:51:00 +00:00
return new LSL_Vector ( ) ;
2008-11-08 23:55:40 +00:00
return detectedParams . Velocity ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llDetectedGrab ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams parms = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-09-26 02:51:00 +00:00
if ( parms = = null )
return new LSL_Vector ( 0 , 0 , 0 ) ;
return parms . OffsetPos ;
}
public LSL_Rotation llDetectedRot ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null )
2008-09-26 02:51:00 +00:00
return new LSL_Rotation ( ) ;
2008-11-08 23:55:40 +00:00
return detectedParams . Rotation ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llDetectedGroup ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null )
2008-09-26 02:51:00 +00:00
return new LSL_Integer ( 0 ) ;
2008-11-08 23:55:40 +00:00
if ( m_host . GroupID = = detectedParams . Group )
2008-09-26 02:51:00 +00:00
return new LSL_Integer ( 1 ) ;
return new LSL_Integer ( 0 ) ;
}
public LSL_Integer llDetectedLinkNumber ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams parms = m_ScriptEngine . GetDetectParams ( m_item . ItemID , number ) ;
2008-09-26 02:51:00 +00:00
if ( parms = = null )
return new LSL_Integer ( 0 ) ;
return new LSL_Integer ( parms . LinkNum ) ;
}
2008-12-05 16:48:47 +00:00
/// <summary>
/// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Vector llDetectedTouchBinormal ( int index )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , index ) ;
2008-12-09 00:51:35 +00:00
if ( detectedParams = = null )
2008-12-05 16:48:47 +00:00
return new LSL_Vector ( ) ;
return detectedParams . TouchBinormal ;
2008-09-26 02:51:00 +00:00
}
2008-12-05 16:48:47 +00:00
/// <summary>
/// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Integer llDetectedTouchFace ( int index )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , index ) ;
2008-12-09 00:51:35 +00:00
if ( detectedParams = = null )
2008-12-05 16:48:47 +00:00
return new LSL_Integer ( - 1 ) ;
return new LSL_Integer ( detectedParams . TouchFace ) ;
2008-09-26 02:51:00 +00:00
}
2008-12-05 16:48:47 +00:00
/// <summary>
/// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Vector llDetectedTouchNormal ( int index )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , index ) ;
2008-12-09 00:51:35 +00:00
if ( detectedParams = = null )
2008-12-05 16:48:47 +00:00
return new LSL_Vector ( ) ;
return detectedParams . TouchNormal ;
2008-09-26 02:51:00 +00:00
}
2008-12-05 16:48:47 +00:00
/// <summary>
/// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Vector llDetectedTouchPos ( int index )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , index ) ;
2008-12-09 00:51:35 +00:00
if ( detectedParams = = null )
2008-12-05 16:48:47 +00:00
return new LSL_Vector ( ) ;
return detectedParams . TouchPos ;
2008-09-26 02:51:00 +00:00
}
2008-12-05 16:48:47 +00:00
/// <summary>
/// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Vector llDetectedTouchST ( int index )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , index ) ;
2008-12-09 00:51:35 +00:00
if ( detectedParams = = null )
2008-12-05 16:48:47 +00:00
return new LSL_Vector ( - 1.0 , - 1.0 , 0.0 ) ;
return detectedParams . TouchST ;
2008-09-26 02:51:00 +00:00
}
2008-12-05 16:48:47 +00:00
/// <summary>
/// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Vector llDetectedTouchUV ( int index )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , index ) ;
2008-12-09 00:51:35 +00:00
if ( detectedParams = = null )
2008-12-05 16:48:47 +00:00
return new LSL_Vector ( - 1.0 , - 1.0 , 0.0 ) ;
return detectedParams . TouchUV ;
2008-09-26 02:51:00 +00:00
}
2009-11-27 08:16:47 +00:00
public virtual void llDie ( )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
throw new SelfDeleteException ( ) ;
}
public LSL_Float llGround ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
Vector3 pos = m_host . GetWorldPosition ( ) + ( Vector3 ) offset ;
2009-06-03 05:31:53 +00:00
//Get the slope normal. This gives us the equation of the plane tangent to the slope.
LSL_Vector vsn = llGroundNormal ( offset ) ;
2008-10-30 15:09:43 +00:00
2008-11-01 07:21:40 +00:00
// Clamp to valid position
2009-06-03 05:31:53 +00:00
if ( pos . X < 0 )
pos . X = 0 ;
else if ( pos . X > = World . Heightmap . Width )
pos . X = World . Heightmap . Width - 1 ;
if ( pos . Y < 0 )
pos . Y = 0 ;
else if ( pos . Y > = World . Heightmap . Height )
pos . Y = World . Heightmap . Height - 1 ;
//Get the height for the integer coordinates from the Heightmap
float baseheight = ( float ) World . Heightmap [ ( int ) pos . X , ( int ) pos . Y ] ;
//Calculate the difference between the actual coordinates and the integer coordinates
float xdiff = pos . X - ( float ) ( ( int ) pos . X ) ;
float ydiff = pos . Y - ( float ) ( ( int ) pos . Y ) ;
//Use the equation of the tangent plane to adjust the height to account for slope
return ( ( ( vsn . x * xdiff ) + ( vsn . y * ydiff ) ) / ( - 1 * vsn . z ) ) + baseheight ;
2008-09-26 02:51:00 +00:00
}
public LSL_Float llCloud ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
2009-04-04 15:43:02 +00:00
float cloudCover = 0f ;
ICloudModule module = World . RequestModuleInterface < ICloudModule > ( ) ;
if ( module ! = null )
{
Vector3 pos = m_host . GetWorldPosition ( ) ;
int x = ( int ) ( pos . X + offset . x ) ;
int y = ( int ) ( pos . Y + offset . y ) ;
cloudCover = module . CloudCover ( x , y , 0 ) ;
}
return cloudCover ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llWind ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-19 21:11:13 +00:00
LSL_Vector wind = new LSL_Vector ( 0 , 0 , 0 ) ;
IWindModule module = World . RequestModuleInterface < IWindModule > ( ) ;
2009-03-05 04:24:22 +00:00
if ( module ! = null )
2008-10-19 21:11:13 +00:00
{
Vector3 pos = m_host . GetWorldPosition ( ) ;
2009-03-05 04:24:22 +00:00
int x = ( int ) ( pos . X + offset . x ) ;
int y = ( int ) ( pos . Y + offset . y ) ;
Vector3 windSpeed = module . WindSpeed ( x , y , 0 ) ;
wind . x = windSpeed . X ;
wind . y = windSpeed . Y ;
2008-10-19 21:11:13 +00:00
}
return wind ;
2008-09-26 02:51:00 +00:00
}
public void llSetStatus ( int status , int value )
{
m_host . AddScriptLPS ( 1 ) ;
int statusrotationaxis = 0 ;
if ( ( status & ScriptBaseClass . STATUS_PHYSICS ) = = ScriptBaseClass . STATUS_PHYSICS )
{
2009-04-02 10:24:12 +00:00
if ( value ! = 0 )
2008-09-26 02:51:00 +00:00
{
SceneObjectGroup group = m_host . ParentGroup ;
bool allow = true ;
2010-09-17 00:30:46 +00:00
foreach ( SceneObjectPart part in group . Parts )
2008-09-26 02:51:00 +00:00
{
2010-09-17 00:30:46 +00:00
if ( part . Scale . X > World . m_maxPhys | | part . Scale . Y > World . m_maxPhys | | part . Scale . Z > World . m_maxPhys )
2008-09-26 02:51:00 +00:00
{
2010-09-17 00:30:46 +00:00
allow = false ;
break ;
2008-09-26 02:51:00 +00:00
}
}
if ( ! allow )
return ;
2011-09-01 00:22:28 +00:00
2008-09-26 02:51:00 +00:00
m_host . ScriptSetPhysicsStatus ( true ) ;
}
else
2011-09-01 00:22:28 +00:00
{
2008-09-26 02:51:00 +00:00
m_host . ScriptSetPhysicsStatus ( false ) ;
2011-09-01 00:22:28 +00:00
}
2008-09-26 02:51:00 +00:00
}
if ( ( status & ScriptBaseClass . STATUS_PHANTOM ) = = ScriptBaseClass . STATUS_PHANTOM )
{
2011-09-01 00:22:28 +00:00
m_host . ParentGroup . ScriptSetPhantomStatus ( value ! = 0 ) ;
2008-09-26 02:51:00 +00:00
}
if ( ( status & ScriptBaseClass . STATUS_CAST_SHADOWS ) = = ScriptBaseClass . STATUS_CAST_SHADOWS )
{
m_host . AddFlag ( PrimFlags . CastShadows ) ;
}
if ( ( status & ScriptBaseClass . STATUS_ROTATE_X ) = = ScriptBaseClass . STATUS_ROTATE_X )
{
statusrotationaxis | = ScriptBaseClass . STATUS_ROTATE_X ;
}
if ( ( status & ScriptBaseClass . STATUS_ROTATE_Y ) = = ScriptBaseClass . STATUS_ROTATE_Y )
{
statusrotationaxis | = ScriptBaseClass . STATUS_ROTATE_Y ;
}
if ( ( status & ScriptBaseClass . STATUS_ROTATE_Z ) = = ScriptBaseClass . STATUS_ROTATE_Z )
{
statusrotationaxis | = ScriptBaseClass . STATUS_ROTATE_Z ;
}
if ( ( status & ScriptBaseClass . STATUS_BLOCK_GRAB ) = = ScriptBaseClass . STATUS_BLOCK_GRAB )
{
2010-02-14 21:41:57 +00:00
if ( value ! = 0 )
m_host . SetBlockGrab ( true ) ;
else
m_host . SetBlockGrab ( false ) ;
2008-09-26 02:51:00 +00:00
}
if ( ( status & ScriptBaseClass . STATUS_DIE_AT_EDGE ) = = ScriptBaseClass . STATUS_DIE_AT_EDGE )
{
2009-04-02 10:24:12 +00:00
if ( value ! = 0 )
2008-09-26 02:51:00 +00:00
m_host . SetDieAtEdge ( true ) ;
else
m_host . SetDieAtEdge ( false ) ;
}
if ( ( status & ScriptBaseClass . STATUS_RETURN_AT_EDGE ) = = ScriptBaseClass . STATUS_RETURN_AT_EDGE )
{
2010-02-14 21:41:57 +00:00
if ( value ! = 0 )
m_host . SetReturnAtEdge ( true ) ;
else
m_host . SetReturnAtEdge ( false ) ;
2008-09-26 02:51:00 +00:00
}
if ( ( status & ScriptBaseClass . STATUS_SANDBOX ) = = ScriptBaseClass . STATUS_SANDBOX )
{
2010-02-14 21:41:57 +00:00
if ( value ! = 0 )
m_host . SetStatusSandbox ( true ) ;
else
m_host . SetStatusSandbox ( false ) ;
2008-09-26 02:51:00 +00:00
}
if ( statusrotationaxis ! = 0 )
{
m_host . SetAxisRotation ( statusrotationaxis , value ) ;
}
}
2012-07-14 00:41:51 +00:00
private bool IsPhysical ( )
{
2012-07-14 00:14:00 +00:00
return ( ( m_host . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . Physics ) = = ( uint ) PrimFlags . Physics ) ;
}
2008-09-26 02:51:00 +00:00
public LSL_Integer llGetStatus ( int status )
{
m_host . AddScriptLPS ( 1 ) ;
2009-02-22 20:52:55 +00:00
// m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
2008-09-26 02:51:00 +00:00
switch ( status )
{
case ScriptBaseClass . STATUS_PHYSICS :
2012-07-14 00:41:51 +00:00
return IsPhysical ( ) ? 1 : 0 ;
2008-09-26 02:51:00 +00:00
case ScriptBaseClass . STATUS_PHANTOM :
if ( ( m_host . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . Phantom ) = = ( uint ) PrimFlags . Phantom )
{
return 1 ;
}
return 0 ;
case ScriptBaseClass . STATUS_CAST_SHADOWS :
if ( ( m_host . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . CastShadows ) = = ( uint ) PrimFlags . CastShadows )
{
return 1 ;
}
return 0 ;
case ScriptBaseClass . STATUS_BLOCK_GRAB :
2010-02-14 21:41:57 +00:00
if ( m_host . GetBlockGrab ( ) )
return 1 ;
else
return 0 ;
2008-09-26 02:51:00 +00:00
case ScriptBaseClass . STATUS_DIE_AT_EDGE :
if ( m_host . GetDieAtEdge ( ) )
return 1 ;
else
return 0 ;
case ScriptBaseClass . STATUS_RETURN_AT_EDGE :
2010-02-14 21:41:57 +00:00
if ( m_host . GetReturnAtEdge ( ) )
return 1 ;
else
return 0 ;
2008-09-26 02:51:00 +00:00
case ScriptBaseClass . STATUS_ROTATE_X :
2010-02-14 21:41:57 +00:00
if ( m_host . GetAxisRotation ( 2 ) = = 2 )
return 1 ;
else
return 0 ;
2008-09-26 02:51:00 +00:00
case ScriptBaseClass . STATUS_ROTATE_Y :
2010-02-14 21:41:57 +00:00
if ( m_host . GetAxisRotation ( 4 ) = = 4 )
return 1 ;
else
return 0 ;
2008-09-26 02:51:00 +00:00
case ScriptBaseClass . STATUS_ROTATE_Z :
2010-02-14 21:41:57 +00:00
if ( m_host . GetAxisRotation ( 8 ) = = 8 )
return 1 ;
else
return 0 ;
2008-09-26 02:51:00 +00:00
case ScriptBaseClass . STATUS_SANDBOX :
2010-02-14 21:41:57 +00:00
if ( m_host . GetStatusSandbox ( ) )
return 1 ;
else
return 0 ;
2008-09-26 02:51:00 +00:00
}
return 0 ;
}
public void llSetScale ( LSL_Vector scale )
{
m_host . AddScriptLPS ( 1 ) ;
SetScale ( m_host , scale ) ;
}
2009-07-06 13:09:03 +00:00
protected void SetScale ( SceneObjectPart part , LSL_Vector scale )
2008-09-26 02:51:00 +00:00
{
// TODO: this needs to trigger a persistance save as well
2011-09-01 00:22:28 +00:00
if ( part = = null | | part . ParentGroup . IsDeleted )
2008-09-26 02:51:00 +00:00
return ;
2011-09-01 00:22:28 +00:00
2012-08-06 14:35:40 +00:00
// First we need to check whether or not we need to clamp the size of a physics-enabled prim
2012-04-03 05:01:05 +00:00
PhysicsActor pa = part . ParentGroup . RootPart . PhysActor ;
if ( pa ! = null & & pa . IsPhysical )
2008-09-26 02:51:00 +00:00
{
2012-08-06 14:35:40 +00:00
scale . x = Math . Max ( World . m_minPhys , Math . Min ( World . m_maxPhys , scale . x ) ) ;
scale . y = Math . Max ( World . m_minPhys , Math . Min ( World . m_maxPhys , scale . y ) ) ;
scale . z = Math . Max ( World . m_minPhys , Math . Min ( World . m_maxPhys , scale . z ) ) ;
2008-09-26 02:51:00 +00:00
}
2012-08-21 11:30:47 +00:00
else
{
// If not physical, then we clamp the scale to the non-physical min/max
scale . x = Math . Max ( World . m_minNonphys , Math . Min ( World . m_maxNonphys , scale . x ) ) ;
scale . y = Math . Max ( World . m_minNonphys , Math . Min ( World . m_maxNonphys , scale . y ) ) ;
scale . z = Math . Max ( World . m_minNonphys , Math . Min ( World . m_maxNonphys , scale . z ) ) ;
}
2009-10-20 13:51:19 +00:00
2008-09-26 02:51:00 +00:00
Vector3 tmp = part . Scale ;
tmp . X = ( float ) scale . x ;
tmp . Y = ( float ) scale . y ;
tmp . Z = ( float ) scale . z ;
part . Scale = tmp ;
part . SendFullUpdateToAllClients ( ) ;
}
public LSL_Vector llGetScale ( )
{
m_host . AddScriptLPS ( 1 ) ;
return new LSL_Vector ( m_host . Scale . X , m_host . Scale . Y , m_host . Scale . Z ) ;
}
public void llSetClickAction ( int action )
{
m_host . AddScriptLPS ( 1 ) ;
2008-09-26 15:18:22 +00:00
m_host . ClickAction = ( byte ) action ;
2011-09-01 00:22:28 +00:00
m_host . ParentGroup . HasGroupChanged = true ;
2008-09-26 15:18:22 +00:00
m_host . ScheduleFullUpdate ( ) ;
2008-09-26 02:51:00 +00:00
return ;
}
public void llSetColor ( LSL_Vector color , int face )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-01 22:29:21 +00:00
if ( face = = ScriptBaseClass . ALL_SIDES )
face = SceneObjectPart . ALL_SIDES ;
2010-09-24 14:26:53 +00:00
2012-08-20 08:31:29 +00:00
m_host . SetFaceColorAlpha ( face , color , null ) ;
2008-09-26 02:51:00 +00:00
}
2009-04-26 00:45:48 +00:00
public void SetTexGen ( SceneObjectPart part , int face , int style )
{
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 ) )
{
tex . CreateFace ( ( uint ) face ) ;
tex . FaceTextures [ face ] . TexMapType = textype ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2009-04-26 00:45:48 +00:00
return ;
}
else if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( uint i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
tex . FaceTextures [ i ] . TexMapType = textype ;
}
tex . DefaultTexture . TexMapType = textype ;
}
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2009-04-26 00:45:48 +00:00
return ;
}
}
2008-09-26 02:51:00 +00:00
public void SetGlow ( SceneObjectPart part , int face , float glow )
{
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
tex . CreateFace ( ( uint ) face ) ;
tex . FaceTextures [ face ] . Glow = glow ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
else if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( uint i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
tex . FaceTextures [ i ] . Glow = glow ;
}
tex . DefaultTexture . Glow = glow ;
}
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
}
public void SetShiny ( SceneObjectPart part , int face , int shiny , Bumpiness bump )
{
Shininess sval = new Shininess ( ) ;
switch ( shiny )
{
case 0 :
sval = Shininess . None ;
break ;
case 1 :
sval = Shininess . Low ;
break ;
case 2 :
sval = Shininess . Medium ;
break ;
case 3 :
sval = Shininess . High ;
break ;
default :
sval = Shininess . None ;
break ;
}
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
tex . CreateFace ( ( uint ) face ) ;
tex . FaceTextures [ face ] . Shiny = sval ;
tex . FaceTextures [ face ] . Bump = bump ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
else if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( uint i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
tex . FaceTextures [ i ] . Shiny = sval ;
tex . FaceTextures [ i ] . Bump = bump ; ;
}
tex . DefaultTexture . Shiny = sval ;
tex . DefaultTexture . Bump = bump ;
}
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
}
public void SetFullBright ( SceneObjectPart part , int face , bool bright )
{
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
tex . CreateFace ( ( uint ) face ) ;
tex . FaceTextures [ face ] . Fullbright = bright ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
else if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( uint i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
tex . FaceTextures [ i ] . Fullbright = bright ;
}
}
tex . DefaultTexture . Fullbright = bright ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
}
public LSL_Float llGetAlpha ( int face )
{
m_host . AddScriptLPS ( 1 ) ;
return GetAlpha ( m_host , face ) ;
}
2009-07-06 13:09:03 +00:00
protected LSL_Float GetAlpha ( SceneObjectPart part , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
int i ;
double sum = 0.0 ;
2010-02-01 22:29:21 +00:00
for ( i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
2008-09-26 02:51:00 +00:00
sum + = ( double ) tex . GetFace ( ( uint ) i ) . RGBA . A ;
return sum ;
}
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
return ( double ) tex . GetFace ( ( uint ) face ) . RGBA . A ;
}
return 0.0 ;
}
public void llSetAlpha ( double alpha , int face )
{
m_host . AddScriptLPS ( 1 ) ;
SetAlpha ( m_host , alpha , face ) ;
}
2008-10-06 14:50:58 +00:00
public void llSetLinkAlpha ( int linknumber , double alpha , int face )
{
m_host . AddScriptLPS ( 1 ) ;
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
foreach ( SceneObjectPart part in parts )
SetAlpha ( part , alpha , face ) ;
}
2009-07-06 13:09:03 +00:00
protected void SetAlpha ( SceneObjectPart part , double alpha , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
Color4 texcolor ;
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
texcolor = tex . CreateFace ( ( uint ) face ) . RGBA ;
texcolor . A = Util . Clip ( ( float ) alpha , 0.0f , 1.0f ) ;
tex . FaceTextures [ face ] . RGBA = texcolor ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
else if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( int i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
texcolor = tex . FaceTextures [ i ] . RGBA ;
texcolor . A = Util . Clip ( ( float ) alpha , 0.0f , 1.0f ) ;
tex . FaceTextures [ i ] . RGBA = texcolor ;
}
}
2011-08-23 17:52:12 +00:00
// In some cases, the default texture can be null, eg when every face
// has a unique texture
if ( tex . DefaultTexture ! = null )
{
texcolor = tex . DefaultTexture . RGBA ;
texcolor . A = Util . Clip ( ( float ) alpha , 0.0f , 1.0f ) ;
tex . DefaultTexture . RGBA = texcolor ;
}
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
}
/// <summary>
/// Set flexi parameters of a part.
///
/// FIXME: Much of this code should probably be within the part itself.
/// </summary>
/// <param name="part"></param>
/// <param name="flexi"></param>
/// <param name="softness"></param>
/// <param name="gravity"></param>
/// <param name="friction"></param>
/// <param name="wind"></param>
/// <param name="tension"></param>
/// <param name="Force"></param>
2009-07-06 13:09:03 +00:00
protected void SetFlexi ( SceneObjectPart part , bool flexi , int softness , float gravity , float friction ,
2008-09-26 02:51:00 +00:00
float wind , float tension , LSL_Vector Force )
{
if ( part = = null )
return ;
if ( flexi )
{
part . Shape . FlexiEntry = true ; // this setting flexi true isn't working, but the below parameters do
2011-11-04 00:06:08 +00:00
// work once the prim is already flexi
2008-09-26 02:51:00 +00:00
part . Shape . FlexiSoftness = softness ;
part . Shape . FlexiGravity = gravity ;
part . Shape . FlexiDrag = friction ;
part . Shape . FlexiWind = wind ;
part . Shape . FlexiTension = tension ;
part . Shape . FlexiForceX = ( float ) Force . x ;
part . Shape . FlexiForceY = ( float ) Force . y ;
part . Shape . FlexiForceZ = ( float ) Force . z ;
part . Shape . PathCurve = 0x80 ;
2011-11-04 00:06:08 +00:00
part . ParentGroup . HasGroupChanged = true ;
part . ScheduleFullUpdate ( ) ;
2008-09-26 02:51:00 +00:00
}
}
/// <summary>
/// Set a light point on a part
/// </summary>
2008-11-17 16:14:23 +00:00
/// FIXME: Much of this code should probably be in SceneObjectGroup
2009-07-28 09:40:07 +00:00
///
2008-09-26 02:51:00 +00:00
/// <param name="part"></param>
/// <param name="light"></param>
/// <param name="color"></param>
/// <param name="intensity"></param>
/// <param name="radius"></param>
/// <param name="falloff"></param>
2009-07-06 13:09:03 +00:00
protected void SetPointLight ( SceneObjectPart part , bool light , LSL_Vector color , float intensity , float radius , float falloff )
2008-09-26 02:51:00 +00:00
{
if ( part = = null )
return ;
if ( light )
{
part . Shape . LightEntry = true ;
part . Shape . LightColorR = Util . Clip ( ( float ) color . x , 0.0f , 1.0f ) ;
part . Shape . LightColorG = Util . Clip ( ( float ) color . y , 0.0f , 1.0f ) ;
part . Shape . LightColorB = Util . Clip ( ( float ) color . z , 0.0f , 1.0f ) ;
part . Shape . LightIntensity = intensity ;
part . Shape . LightRadius = radius ;
part . Shape . LightFalloff = falloff ;
}
else
{
part . Shape . LightEntry = false ;
}
part . ParentGroup . HasGroupChanged = true ;
part . ScheduleFullUpdate ( ) ;
}
public LSL_Vector llGetColor ( int face )
{
m_host . AddScriptLPS ( 1 ) ;
return GetColor ( m_host , face ) ;
}
2009-07-06 13:09:03 +00:00
protected LSL_Vector GetColor ( SceneObjectPart part , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
Color4 texcolor ;
LSL_Vector rgb = new LSL_Vector ( ) ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
int i ;
2010-02-01 22:29:21 +00:00
for ( i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
2008-09-26 02:51:00 +00:00
{
texcolor = tex . GetFace ( ( uint ) i ) . RGBA ;
rgb . x + = texcolor . R ;
rgb . y + = texcolor . G ;
rgb . z + = texcolor . B ;
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
rgb . x / = ( float ) GetNumberOfSides ( part ) ;
rgb . y / = ( float ) GetNumberOfSides ( part ) ;
rgb . z / = ( float ) GetNumberOfSides ( part ) ;
return rgb ;
}
2012-05-26 00:03:53 +00:00
2008-09-26 02:51:00 +00:00
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
texcolor = tex . GetFace ( ( uint ) face ) . RGBA ;
rgb . x = texcolor . R ;
rgb . y = texcolor . G ;
rgb . z = texcolor . B ;
2012-05-26 00:03:53 +00:00
2008-09-26 02:51:00 +00:00
return rgb ;
}
else
{
return new LSL_Vector ( ) ;
}
}
public void llSetTexture ( string texture , int face )
{
m_host . AddScriptLPS ( 1 ) ;
SetTexture ( m_host , texture , face ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 200 ) ;
2008-09-26 02:51:00 +00:00
}
2008-10-07 14:58:56 +00:00
public void llSetLinkTexture ( int linknumber , string texture , int face )
{
m_host . AddScriptLPS ( 1 ) ;
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
foreach ( SceneObjectPart part in parts )
SetTexture ( part , texture , face ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 200 ) ;
2008-10-07 14:58:56 +00:00
}
2009-07-06 13:09:03 +00:00
protected void SetTexture ( SceneObjectPart part , string texture , int face )
2008-09-26 02:51:00 +00:00
{
2011-02-04 21:55:22 +00:00
UUID textureID = new UUID ( ) ;
textureID = InventoryKey ( texture , ( int ) AssetType . Texture ) ;
if ( textureID = = UUID . Zero )
{
if ( ! UUID . TryParse ( texture , out textureID ) )
return ;
}
2008-09-26 02:51:00 +00:00
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
Primitive . TextureEntryFace texface = tex . CreateFace ( ( uint ) face ) ;
texface . TextureID = textureID ;
tex . FaceTextures [ face ] = texface ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
else if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( uint i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
tex . FaceTextures [ i ] . TextureID = textureID ;
}
}
tex . DefaultTexture . TextureID = textureID ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
}
public void llScaleTexture ( double u , double v , int face )
{
m_host . AddScriptLPS ( 1 ) ;
ScaleTexture ( m_host , u , v , face ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 200 ) ;
2008-09-26 02:51:00 +00:00
}
2009-07-06 13:09:03 +00:00
protected void ScaleTexture ( SceneObjectPart part , double u , double v , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
Primitive . TextureEntryFace texface = tex . CreateFace ( ( uint ) face ) ;
texface . RepeatU = ( float ) u ;
texface . RepeatV = ( float ) v ;
tex . FaceTextures [ face ] = texface ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( int i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
tex . FaceTextures [ i ] . RepeatU = ( float ) u ;
tex . FaceTextures [ i ] . RepeatV = ( float ) v ;
}
}
tex . DefaultTexture . RepeatU = ( float ) u ;
tex . DefaultTexture . RepeatV = ( float ) v ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
}
public void llOffsetTexture ( double u , double v , int face )
{
m_host . AddScriptLPS ( 1 ) ;
OffsetTexture ( m_host , u , v , face ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 200 ) ;
2008-09-26 02:51:00 +00:00
}
2009-07-06 13:09:03 +00:00
protected void OffsetTexture ( SceneObjectPart part , double u , double v , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
Primitive . TextureEntryFace texface = tex . CreateFace ( ( uint ) face ) ;
texface . OffsetU = ( float ) u ;
texface . OffsetV = ( float ) v ;
tex . FaceTextures [ face ] = texface ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( int i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
tex . FaceTextures [ i ] . OffsetU = ( float ) u ;
tex . FaceTextures [ i ] . OffsetV = ( float ) v ;
}
}
tex . DefaultTexture . OffsetU = ( float ) u ;
tex . DefaultTexture . OffsetV = ( float ) v ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
}
public void llRotateTexture ( double rotation , int face )
{
m_host . AddScriptLPS ( 1 ) ;
RotateTexture ( m_host , rotation , face ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 200 ) ;
2008-09-26 02:51:00 +00:00
}
2009-07-06 13:09:03 +00:00
protected void RotateTexture ( SceneObjectPart part , double rotation , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
Primitive . TextureEntryFace texface = tex . CreateFace ( ( uint ) face ) ;
texface . Rotation = ( float ) rotation ;
tex . FaceTextures [ face ] = texface ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( int i = 0 ; i < GetNumberOfSides ( part ) ; i + + )
{
if ( tex . FaceTextures [ i ] ! = null )
{
tex . FaceTextures [ i ] . Rotation = ( float ) rotation ;
}
}
tex . DefaultTexture . Rotation = ( float ) rotation ;
2011-12-05 19:01:14 +00:00
part . UpdateTextureEntry ( tex . GetBytes ( ) ) ;
2008-09-26 02:51:00 +00:00
return ;
}
}
public LSL_String llGetTexture ( int face )
{
m_host . AddScriptLPS ( 1 ) ;
return GetTexture ( m_host , face ) ;
}
2009-07-06 13:09:03 +00:00
protected LSL_String GetTexture ( SceneObjectPart part , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
face = 0 ;
}
2011-10-03 23:07:52 +00:00
2008-09-26 02:51:00 +00:00
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
Primitive . TextureEntryFace texface ;
texface = tex . GetFace ( ( uint ) face ) ;
2011-10-03 23:07:52 +00:00
string texture = texface . TextureID . ToString ( ) ;
lock ( part . TaskInventory )
{
foreach ( KeyValuePair < UUID , TaskInventoryItem > inv in part . TaskInventory )
{
if ( inv . Value . AssetID = = texface . TextureID )
{
texture = inv . Value . Name . ToString ( ) ;
break ;
}
}
}
return texture ;
2008-09-26 02:51:00 +00:00
}
else
{
2011-10-03 23:15:48 +00:00
return UUID . Zero . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
}
public void llSetPos ( LSL_Vector pos )
{
m_host . AddScriptLPS ( 1 ) ;
2012-07-12 11:25:08 +00:00
SetPos ( m_host , pos , true ) ;
2008-09-26 02:51:00 +00:00
ScriptSleep ( 200 ) ;
}
2009-07-28 09:40:07 +00:00
2012-07-12 11:25:08 +00:00
/// <summary>
/// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos
/// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into.
/// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking.
/// </summary>
/// <param name="pos"></param>
/// <returns>1 if successful, 0 otherwise.</returns>
public LSL_Integer llSetRegionPos ( LSL_Vector pos )
{
m_host . AddScriptLPS ( 1 ) ;
2012-07-12 14:57:22 +00:00
// BEGIN WORKAROUND
// IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
/ /
// This workaround is to prevent silent failure of this function.
// According to the specification on the SL Wiki, providing a position outside of the
if ( pos . x < 0 | | pos . x > Constants . RegionSize | | pos . y < 0 | | pos . y > Constants . RegionSize )
{
2012-07-12 11:25:08 +00:00
return 0 ;
}
2012-07-12 14:57:22 +00:00
// END WORK AROUND
2012-07-14 00:14:00 +00:00
else if ( // this is not part of the workaround if-block because it's not related to the workaround.
2012-07-14 00:41:51 +00:00
IsPhysical ( ) | |
2012-07-14 00:14:00 +00:00
m_host . ParentGroup . IsAttachment | | // return FALSE if attachment
(
pos . x < - 10.0 | | // return FALSE if more than 10 meters into a west-adjacent region.
pos . x > ( Constants . RegionSize + 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 > ( Constants . RegionSize + 10 ) | | // return FALSE if more than 10 meters into a north-adjacent region.
pos . z > 4096 // return FALSE if altitude than 4096m
)
)
{
return 0 ;
}
// if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range.
// this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
2012-07-12 11:25:08 +00:00
2012-07-14 00:14:00 +00:00
Vector3 objectPos = m_host . ParentGroup . RootPart . AbsolutePosition ;
LandData here = World . GetLandData ( ( float ) objectPos . X , ( float ) objectPos . Y ) ;
LandData there = World . GetLandData ( ( float ) pos . x , ( float ) pos . y ) ;
2012-07-12 11:25:08 +00:00
2012-07-14 00:14:00 +00:00
// we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
bool sameParcel = here . GlobalID = = there . GlobalID ;
2012-08-18 00:17:01 +00:00
if ( ! sameParcel & & ! World . Permissions . CanRezObject (
m_host . ParentGroup . PrimCount , m_host . ParentGroup . OwnerID , pos ) )
2012-07-14 00:14:00 +00:00
{
return 0 ;
2012-07-12 14:57:22 +00:00
}
2012-07-14 00:14:00 +00:00
SetPos ( m_host . ParentGroup . RootPart , pos , false ) ;
2012-07-14 00:41:51 +00:00
return VecDist ( pos , llGetRootPosition ( ) ) < = 0.1 ? 1 : 0 ;
2012-07-12 11:25:08 +00:00
}
2009-07-28 09:40:07 +00:00
// Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
// note linked setpos is capped "differently"
private LSL_Vector SetPosAdjust ( LSL_Vector start , LSL_Vector end )
{
if ( llVecDist ( start , end ) > 10.0f * m_ScriptDistanceFactor )
return start + m_ScriptDistanceFactor * 10.0f * llVecNorm ( end - start ) ;
else
return end ;
}
2011-11-02 12:02:44 +00:00
protected LSL_Vector GetSetPosTarget ( SceneObjectPart part , LSL_Vector targetPos , LSL_Vector fromPos )
{
if ( part = = null | | part . ParentGroup = = null | | part . ParentGroup . IsDeleted )
return fromPos ;
// Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
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 ;
}
LSL_Vector real_vec = SetPosAdjust ( fromPos , targetPos ) ;
return real_vec ;
}
2012-07-12 11:25:08 +00:00
/// <summary>
/// set object position, optionally capping the distance.
/// </summary>
/// <param name="part"></param>
/// <param name="targetPos"></param>
/// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
protected void SetPos ( SceneObjectPart part , LSL_Vector targetPos , bool adjust )
2008-09-26 02:51:00 +00:00
{
// Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2010-08-06 16:55:41 +00:00
LSL_Vector currentPos = GetPartLocalPos ( part ) ;
2008-09-26 02:51:00 +00:00
2009-07-08 10:22:51 +00:00
float ground = World . GetGroundHeight ( ( float ) targetPos . x , ( float ) targetPos . y ) ;
2009-07-08 14:36:00 +00:00
bool disable_underground_movement = m_ScriptEngine . Config . GetBoolean ( "DisableUndergroundMovement" , true ) ;
2010-05-05 19:12:02 +00:00
if ( part . ParentGroup . RootPart = = part )
2008-09-26 02:51:00 +00:00
{
2011-08-26 23:15:21 +00:00
if ( ( targetPos . z < ground ) & & disable_underground_movement & & m_host . ParentGroup . AttachmentPoint = = 0 )
2009-07-11 11:47:33 +00:00
targetPos . z = ground ;
2008-10-08 01:49:58 +00:00
SceneObjectGroup parent = part . ParentGroup ;
2012-08-18 00:17:01 +00:00
parent . UpdateGroupPosition ( ! adjust ? targetPos :
SetPosAdjust ( currentPos , targetPos ) ) ;
2008-09-26 02:51:00 +00:00
}
2008-10-11 23:47:35 +00:00
else
2009-07-28 09:40:07 +00:00
{
2012-08-18 13:00:10 +00:00
part . OffsetPosition = ! adjust ? targetPos :
SetPosAdjust ( currentPos , targetPos ) ;
2010-07-31 00:03:14 +00:00
SceneObjectGroup parent = part . ParentGroup ;
parent . HasGroupChanged = true ;
parent . ScheduleGroupForTerseUpdate ( ) ;
2009-07-28 09:40:07 +00:00
}
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGetPos ( )
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-07 11:41:43 +00:00
Vector3 pos = m_host . GetWorldPosition ( ) ;
return new LSL_Vector ( pos . X , pos . Y , pos . Z ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGetLocalPos ( )
{
m_host . AddScriptLPS ( 1 ) ;
2010-08-06 16:37:34 +00:00
return GetPartLocalPos ( m_host ) ;
}
protected LSL_Vector GetPartLocalPos ( SceneObjectPart part )
{
m_host . AddScriptLPS ( 1 ) ;
2012-04-06 21:41:35 +00:00
Vector3 pos ;
2012-04-06 22:36:13 +00:00
if ( ! part . IsRoot )
2008-09-26 02:51:00 +00:00
{
2012-04-06 22:36:13 +00:00
pos = part . OffsetPosition ;
2008-09-26 02:51:00 +00:00
}
2010-08-24 08:33:50 +00:00
else
{
2012-04-06 22:36:13 +00:00
if ( part . ParentGroup . IsAttachment )
2010-08-24 08:33:50 +00:00
{
2012-04-06 21:41:35 +00:00
pos = part . AttachedPos ;
2010-08-24 08:33:50 +00:00
}
else
{
2012-04-06 22:36:13 +00:00
pos = part . AbsolutePosition ;
2010-08-24 08:33:50 +00:00
}
}
2012-04-06 21:41:35 +00:00
// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2012-08-18 00:17:01 +00:00
return new LSL_Vector ( pos ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetRot ( LSL_Rotation rot )
{
m_host . AddScriptLPS ( 1 ) ;
2008-11-15 21:03:06 +00:00
// try to let this work as in SL...
2010-10-29 19:17:59 +00:00
if ( m_host . ParentID = = 0 )
{
// special case: If we are root, rotate complete SOG to new rotation
2012-08-18 14:18:31 +00:00
SetRot ( m_host , rot ) ;
2008-11-15 21:03:06 +00:00
}
else
{
// we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
2011-09-01 00:22:28 +00:00
SceneObjectPart rootPart = m_host . ParentGroup . RootPart ;
if ( rootPart ! = null ) // better safe than sorry
2008-11-15 21:03:06 +00:00
{
2012-08-18 14:18:31 +00:00
SetRot ( m_host , rootPart . RotationOffset * ( Quaternion ) rot ) ;
2008-11-15 21:03:06 +00:00
}
}
ScriptSleep ( 200 ) ;
}
2008-09-26 02:51:00 +00:00
2008-11-15 21:03:06 +00:00
public void llSetLocalRot ( LSL_Rotation rot )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 14:18:31 +00:00
SetRot ( m_host , rot ) ;
2008-09-26 02:51:00 +00:00
ScriptSleep ( 200 ) ;
}
2009-07-06 13:09:03 +00:00
protected void SetRot ( SceneObjectPart part , Quaternion rot )
2008-09-26 02:51:00 +00:00
{
2008-11-15 21:03:06 +00:00
part . UpdateRotation ( rot ) ;
2008-09-26 02:51:00 +00:00
// Update rotation does not move the object in the physics scene if it's a linkset.
2009-09-30 16:51:02 +00:00
//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;
2010-09-24 14:26:53 +00:00
2009-11-26 06:34:46 +00:00
// 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
2012-04-03 05:01:05 +00:00
PhysicsActor pa = part . PhysActor ;
if ( pa ! = null & & ! pa . IsPhysical )
2009-11-26 06:34:46 +00:00
{
part . ParentGroup . ResetChildPrimPhysicsPositions ( ) ;
}
2008-09-26 02:51:00 +00:00
}
2009-01-23 18:10:31 +00:00
/// <summary>
/// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Rotation llGetRot ( )
{
2008-10-27 00:51:50 +00:00
// unlinked or root prim then use llRootRotation
// see llRootRotaion for references.
if ( m_host . LinkNum = = 0 | | m_host . LinkNum = = 1 )
{
return llGetRootRotation ( ) ;
}
2011-08-11 22:28:14 +00:00
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
2009-01-23 18:10:31 +00:00
Quaternion q = m_host . GetWorldRotation ( ) ;
2008-09-26 02:51:00 +00:00
return new LSL_Rotation ( q . X , q . Y , q . Z , q . W ) ;
}
2009-08-21 06:42:36 +00:00
private LSL_Rotation GetPartRot ( SceneObjectPart part )
2009-08-20 22:51:43 +00:00
{
Quaternion q ;
if ( part . LinkNum = = 0 | | part . LinkNum = = 1 ) // unlinked or root prim
{
2011-08-26 23:15:21 +00:00
if ( part . ParentGroup . AttachmentPoint ! = 0 )
2009-08-21 06:42:36 +00:00
{
2011-08-26 22:06:41 +00:00
ScenePresence avatar = World . GetScenePresence ( part . ParentGroup . AttachedAvatar ) ;
2009-08-21 06:42:36 +00:00
if ( avatar ! = null )
{
if ( ( avatar . AgentControlFlags & ( uint ) AgentManager . ControlFlags . AGENT_CONTROL_MOUSELOOK ) ! = 0 )
q = avatar . CameraRotation ; // Mouselook
else
q = avatar . Rotation ; // Currently infrequently updated so may be inaccurate
}
else
2009-10-01 23:45:31 +00:00
q = part . ParentGroup . GroupRotation ; // Likely never get here but just in case
2009-08-21 06:42:36 +00:00
}
else
2009-10-01 23:45:31 +00:00
q = part . ParentGroup . GroupRotation ; // just the group rotation
2009-08-21 06:42:36 +00:00
return new LSL_Rotation ( q . X , q . Y , q . Z , q . W ) ;
2009-08-20 22:51:43 +00:00
}
q = part . GetWorldRotation ( ) ;
return new LSL_Rotation ( q . X , q . Y , q . Z , q . W ) ;
}
2008-09-26 02:51:00 +00:00
public LSL_Rotation llGetLocalRot ( )
{
m_host . AddScriptLPS ( 1 ) ;
return new LSL_Rotation ( m_host . RotationOffset . X , m_host . RotationOffset . Y , m_host . RotationOffset . Z , m_host . RotationOffset . W ) ;
}
public void llSetForce ( LSL_Vector force , int local )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2008-09-26 02:51:00 +00:00
{
2011-09-01 00:22:28 +00:00
if ( local ! = 0 )
force * = llGetRot ( ) ;
2008-09-26 02:51:00 +00:00
2012-08-18 00:17:01 +00:00
m_host . ParentGroup . RootPart . SetForce ( force ) ;
2008-09-26 02:51:00 +00:00
}
}
public LSL_Vector llGetForce ( )
{
LSL_Vector force = new LSL_Vector ( 0.0 , 0.0 , 0.0 ) ;
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2008-09-26 02:51:00 +00:00
{
2012-08-18 00:17:01 +00:00
force = m_host . ParentGroup . RootPart . GetForce ( ) ;
2008-09-26 02:51:00 +00:00
}
return force ;
}
public LSL_Integer llTarget ( LSL_Vector position , double range )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
return m_host . ParentGroup . registerTargetWaypoint ( position ,
( float ) range ) ;
2008-09-26 02:51:00 +00:00
}
public void llTargetRemove ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 01:18:31 +00:00
m_host . ParentGroup . unregisterTargetWaypoint ( number ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llRotTarget ( LSL_Rotation rot , double error )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 14:04:07 +00:00
return m_host . ParentGroup . registerRotTargetWaypoint ( rot , ( float ) error ) ;
2008-09-26 02:51:00 +00:00
}
public void llRotTargetRemove ( int number )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 01:18:31 +00:00
m_host . ParentGroup . unregisterRotTargetWaypoint ( number ) ;
2008-09-26 02:51:00 +00:00
}
public void llMoveToTarget ( LSL_Vector target , double tau )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
m_host . MoveToTarget ( target , ( float ) tau ) ;
2008-09-26 02:51:00 +00:00
}
public void llStopMoveToTarget ( )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . StopMoveToTarget ( ) ;
}
public void llApplyImpulse ( LSL_Vector force , int local )
{
m_host . AddScriptLPS ( 1 ) ;
//No energy force yet
2012-08-18 00:17:01 +00:00
Vector3 v = force ;
2009-04-02 10:24:12 +00:00
if ( v . Length ( ) > 20000.0f )
{
v . Normalize ( ) ;
v = v * 20000.0f ;
}
m_host . ApplyImpulse ( v , local ! = 0 ) ;
2008-09-26 02:51:00 +00:00
}
public void llApplyRotationalImpulse ( LSL_Vector force , int local )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
m_host . ApplyAngularImpulse ( force , local ! = 0 ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetTorque ( LSL_Vector torque , int local )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
m_host . SetAngularImpulse ( torque , local ! = 0 ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGetTorque ( )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:37:35 +00:00
Vector3 torque = m_host . ParentGroup . GetTorque ( ) ;
2008-12-14 14:30:28 +00:00
return new LSL_Vector ( torque . X , torque . Y , torque . Z ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetForceAndTorque ( LSL_Vector force , LSL_Vector torque , int local )
{
m_host . AddScriptLPS ( 1 ) ;
2008-12-14 14:30:28 +00:00
llSetForce ( force , local ) ;
llSetTorque ( torque , local ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGetVel ( )
{
m_host . AddScriptLPS ( 1 ) ;
2011-07-15 22:36:32 +00:00
Vector3 vel ;
2011-08-26 23:15:21 +00:00
if ( m_host . ParentGroup . IsAttachment )
2011-07-15 22:36:32 +00:00
{
2011-08-26 22:06:41 +00:00
ScenePresence avatar = m_host . ParentGroup . Scene . GetScenePresence ( m_host . ParentGroup . AttachedAvatar ) ;
2011-07-15 22:36:32 +00:00
vel = avatar . Velocity ;
}
else
{
vel = m_host . Velocity ;
}
return new LSL_Vector ( vel . X , vel . Y , vel . Z ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGetAccel ( )
{
m_host . AddScriptLPS ( 1 ) ;
return new LSL_Vector ( m_host . Acceleration . X , m_host . Acceleration . Y , m_host . Acceleration . Z ) ;
}
public LSL_Vector llGetOmega ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-11-02 19:28:35 +00:00
return new LSL_Vector ( m_host . AngularVelocity . X , m_host . AngularVelocity . Y , m_host . AngularVelocity . Z ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Float llGetTimeOfDay ( )
{
m_host . AddScriptLPS ( 1 ) ;
2008-12-14 17:48:27 +00:00
return ( double ) ( ( DateTime . Now . TimeOfDay . TotalMilliseconds / 1000 ) % ( 3600 * 4 ) ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Float llGetWallclock ( )
{
m_host . AddScriptLPS ( 1 ) ;
return DateTime . Now . TimeOfDay . TotalSeconds ;
}
public LSL_Float llGetTime ( )
{
m_host . AddScriptLPS ( 1 ) ;
TimeSpan ScriptTime = DateTime . Now - m_timer ;
2008-12-14 17:48:27 +00:00
return ( double ) ( ScriptTime . TotalMilliseconds / 1000 ) ;
2008-09-26 02:51:00 +00:00
}
public void llResetTime ( )
{
m_host . AddScriptLPS ( 1 ) ;
m_timer = DateTime . Now ;
}
public LSL_Float llGetAndResetTime ( )
{
m_host . AddScriptLPS ( 1 ) ;
TimeSpan ScriptTime = DateTime . Now - m_timer ;
m_timer = DateTime . Now ;
2008-12-14 17:48:27 +00:00
return ( double ) ( ScriptTime . TotalMilliseconds / 1000 ) ;
2008-09-26 02:51:00 +00:00
}
2008-09-30 01:59:51 +00:00
public void llSound ( string sound , double volume , int queue , int loop )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
// This function has been deprecated
// see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
Deprecated ( "llSound" ) ;
}
// Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
// 20080530 Updated to remove code duplication
public void llPlaySound ( string sound , double volume )
{
m_host . AddScriptLPS ( 1 ) ;
// send the sound, once, to all clients in range
2010-02-14 21:41:57 +00:00
m_host . SendSound ( KeyOrName ( sound ) . ToString ( ) , volume , false , 0 , 0 , false , false ) ;
2008-09-26 02:51:00 +00:00
}
// Xantor 20080528 we should do this differently.
// 1) apply the sound to the object
// 2) schedule full update
// just sending the sound out once doesn't work so well when other avatars come in view later on
// or when the prim gets moved, changed, sat on, whatever
// see large number of mantises (mantes?)
// 20080530 Updated to remove code duplication
// 20080530 Stop sound if there is one, otherwise volume only changes don't work
public void llLoopSound ( string sound , double volume )
{
m_host . AddScriptLPS ( 1 ) ;
if ( m_host . Sound ! = UUID . Zero )
llStopSound ( ) ;
m_host . Sound = KeyOrName ( sound ) ;
m_host . SoundGain = volume ;
m_host . SoundFlags = 1 ; // looping
m_host . SoundRadius = 20 ; // Magic number, 20 seems reasonable. Make configurable?
m_host . ScheduleFullUpdate ( ) ;
m_host . SendFullUpdateToAllClients ( ) ;
}
public void llLoopSoundMaster ( string sound , double volume )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-14 21:41:57 +00:00
m_host . ParentGroup . LoopSoundMasterPrim = m_host ;
lock ( m_host . ParentGroup . LoopSoundSlavePrims )
{
foreach ( SceneObjectPart prim in m_host . ParentGroup . LoopSoundSlavePrims )
{
if ( prim . Sound ! = UUID . Zero )
llStopSound ( ) ;
prim . Sound = KeyOrName ( sound ) ;
prim . SoundGain = volume ;
prim . SoundFlags = 1 ; // looping
prim . SoundRadius = 20 ; // Magic number, 20 seems reasonable. Make configurable?
prim . ScheduleFullUpdate ( ) ;
prim . SendFullUpdateToAllClients ( ) ;
}
}
if ( m_host . Sound ! = UUID . Zero )
llStopSound ( ) ;
m_host . Sound = KeyOrName ( sound ) ;
m_host . SoundGain = volume ;
m_host . SoundFlags = 1 ; // looping
m_host . SoundRadius = 20 ; // Magic number, 20 seems reasonable. Make configurable?
m_host . ScheduleFullUpdate ( ) ;
m_host . SendFullUpdateToAllClients ( ) ;
2008-09-26 02:51:00 +00:00
}
public void llLoopSoundSlave ( string sound , double volume )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-14 21:41:57 +00:00
lock ( m_host . ParentGroup . LoopSoundSlavePrims )
{
m_host . ParentGroup . LoopSoundSlavePrims . Add ( m_host ) ;
}
2008-09-26 02:51:00 +00:00
}
public void llPlaySoundSlave ( string sound , double volume )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-14 21:41:57 +00:00
// send the sound, once, to all clients in range
m_host . SendSound ( KeyOrName ( sound ) . ToString ( ) , volume , false , 0 , 0 , true , false ) ;
2008-09-26 02:51:00 +00:00
}
public void llTriggerSound ( string sound , double volume )
{
m_host . AddScriptLPS ( 1 ) ;
// send the sound, once, to all clients in range
2010-02-14 21:41:57 +00:00
m_host . SendSound ( KeyOrName ( sound ) . ToString ( ) , volume , true , 0 , 0 , false , false ) ;
2008-09-26 02:51:00 +00:00
}
// Xantor 20080528: Clear prim data of sound instead
public void llStopSound ( )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-14 21:41:57 +00:00
if ( m_host . ParentGroup . LoopSoundSlavePrims . Contains ( m_host ) )
{
if ( m_host . ParentGroup . LoopSoundMasterPrim = = m_host )
{
foreach ( SceneObjectPart part in m_host . ParentGroup . LoopSoundSlavePrims )
{
part . Sound = UUID . Zero ;
part . SoundGain = 0 ;
part . SoundFlags = 0 ;
part . SoundRadius = 0 ;
part . ScheduleFullUpdate ( ) ;
part . SendFullUpdateToAllClients ( ) ;
}
m_host . ParentGroup . LoopSoundMasterPrim = null ;
m_host . ParentGroup . LoopSoundSlavePrims . Clear ( ) ;
}
else
{
m_host . Sound = UUID . Zero ;
m_host . SoundGain = 0 ;
m_host . SoundFlags = 0 ;
m_host . SoundRadius = 0 ;
m_host . ScheduleFullUpdate ( ) ;
m_host . SendFullUpdateToAllClients ( ) ;
}
}
else
{
m_host . Sound = UUID . Zero ;
m_host . SoundGain = 0 ;
m_host . SoundFlags = 0 ;
m_host . SoundRadius = 0 ;
m_host . ScheduleFullUpdate ( ) ;
m_host . SendFullUpdateToAllClients ( ) ;
}
2008-09-26 02:51:00 +00:00
}
public void llPreloadSound ( string sound )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . PreloadSound ( sound ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
}
/// <summary>
/// Return a portion of the designated string bounded by
/// inclusive indices (start and end). As usual, the negative
/// indices, and the tolerance for out-of-bound values, makes
/// this more complicated than it might otherwise seem.
/// </summary>
public LSL_String llGetSubString ( string src , int start , int end )
{
m_host . AddScriptLPS ( 1 ) ;
// Normalize indices (if negative).
// After normlaization they may still be
// negative, but that is now relative to
// the start, rather than the end, of the
// sequence.
if ( start < 0 )
{
start = src . Length + start ;
}
if ( end < 0 )
{
end = src . Length + end ;
}
// Conventional substring
if ( start < = end )
{
// Implies both bounds are out-of-range.
if ( end < 0 | | start > = src . Length )
{
return String . Empty ;
}
// If end is positive, then it directly
// corresponds to the lengt of the substring
// needed (plus one of course). BUT, it
// must be within bounds.
if ( end > = src . Length )
{
end = src . Length - 1 ;
}
if ( start < 0 )
{
return src . Substring ( 0 , end + 1 ) ;
}
// Both indices are positive
return src . Substring ( start , ( end + 1 ) - start ) ;
}
// Inverted substring (end < start)
else
{
// Implies both indices are below the
// lower bound. In the inverted case, that
// means the entire string will be returned
// unchanged.
if ( start < 0 )
{
return src ;
}
// If both indices are greater than the upper
// bound the result may seem initially counter
// intuitive.
if ( end > = src . Length )
{
return src ;
}
if ( end < 0 )
{
if ( start < src . Length )
{
return src . Substring ( start ) ;
}
else
{
return String . Empty ;
}
}
else
{
if ( start < src . Length )
{
return src . Substring ( 0 , end + 1 ) + src . Substring ( start ) ;
}
else
{
return src . Substring ( 0 , end + 1 ) ;
}
}
}
}
/// <summary>
/// Delete substring removes the specified substring bounded
/// by the inclusive indices start and end. Indices may be
/// negative (indicating end-relative) and may be inverted,
/// i.e. end < start.
/// </summary>
public LSL_String llDeleteSubString ( string src , int start , int end )
{
m_host . AddScriptLPS ( 1 ) ;
// Normalize indices (if negative).
// After normlaization they may still be
// negative, but that is now relative to
// the start, rather than the end, of the
// sequence.
if ( start < 0 )
{
start = src . Length + start ;
}
if ( end < 0 )
{
end = src . Length + end ;
}
// Conventionally delimited substring
if ( start < = end )
{
// If both bounds are outside of the existing
// string, then return unchanges.
if ( end < 0 | | start > = src . Length )
{
return src ;
}
// At least one bound is in-range, so we
// need to clip the out-of-bound argument.
if ( start < 0 )
{
start = 0 ;
}
if ( end > = src . Length )
{
end = src . Length - 1 ;
}
return src . Remove ( start , end - start + 1 ) ;
}
// Inverted substring
else
{
// In this case, out of bounds means that
// the existing string is part of the cut.
if ( start < 0 | | end > = src . Length )
{
return String . Empty ;
}
if ( end > 0 )
{
if ( start < src . Length )
{
return src . Remove ( start ) . Remove ( 0 , end + 1 ) ;
}
else
{
return src . Remove ( 0 , end + 1 ) ;
}
}
else
{
if ( start < src . Length )
{
return src . Remove ( start ) ;
}
else
{
return src ;
}
}
}
}
/// <summary>
/// Insert string inserts the specified string identified by src
/// at the index indicated by index. Index may be negative, in
/// which case it is end-relative. The index may exceed either
/// string bound, with the result being a concatenation.
/// </summary>
public LSL_String llInsertString ( string dest , int index , string src )
{
m_host . AddScriptLPS ( 1 ) ;
// Normalize indices (if negative).
// After normlaization they may still be
// negative, but that is now relative to
// the start, rather than the end, of the
// sequence.
if ( index < 0 )
{
index = dest . Length + index ;
// Negative now means it is less than the lower
// bound of the string.
if ( index < 0 )
{
return src + dest ;
}
}
if ( index > = dest . Length )
{
return dest + src ;
}
// The index is in bounds.
// In this case the index refers to the index that will
// be assigned to the first character of the inserted string.
// So unlike the other string operations, we do not add one
// to get the correct string length.
return dest . Substring ( 0 , index ) + src + dest . Substring ( index ) ;
}
public LSL_String llToUpper ( string src )
{
m_host . AddScriptLPS ( 1 ) ;
return src . ToUpper ( ) ;
}
public LSL_String llToLower ( string src )
{
m_host . AddScriptLPS ( 1 ) ;
return src . ToLower ( ) ;
}
public LSL_Integer llGiveMoney ( string destination , int amount )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter = = UUID . Zero )
2008-09-26 02:51:00 +00:00
return 0 ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_DEBIT ) = = 0 )
2008-09-26 02:51:00 +00:00
{
LSLError ( "No permissions to give money" ) ;
return 0 ;
}
2009-02-20 14:04:29 +00:00
UUID toID = new UUID ( ) ;
2008-09-26 02:51:00 +00:00
if ( ! UUID . TryParse ( destination , out toID ) )
{
LSLError ( "Bad key in llGiveMoney" ) ;
return 0 ;
}
2009-02-20 14:04:29 +00:00
IMoneyModule money = World . RequestModuleInterface < IMoneyModule > ( ) ;
2008-09-26 02:51:00 +00:00
if ( money = = null )
{
NotImplemented ( "llGiveMoney" ) ;
return 0 ;
}
2009-07-28 09:40:07 +00:00
bool result = money . ObjectGiveMoney (
m_host . ParentGroup . RootPart . UUID , m_host . ParentGroup . RootPart . OwnerID , toID , amount ) ;
2008-09-26 02:51:00 +00:00
if ( result )
return 1 ;
return 0 ;
}
2008-09-30 01:59:51 +00:00
public void llMakeExplosion ( int particles , double scale , double vel , double lifetime , double arc , string texture , LSL_Vector offset )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
Deprecated ( "llMakeExplosion" ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
2009-02-01 15:12:32 +00:00
public void llMakeFountain ( int particles , double scale , double vel , double lifetime , double arc , int bounce , string texture , LSL_Vector offset , double bounce_offset )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
Deprecated ( "llMakeFountain" ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
2008-09-30 01:59:51 +00:00
public void llMakeSmoke ( int particles , double scale , double vel , double lifetime , double arc , string texture , LSL_Vector offset )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
Deprecated ( "llMakeSmoke" ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
2008-09-30 01:59:51 +00:00
public void llMakeFire ( int particles , double scale , double vel , double lifetime , double arc , string texture , LSL_Vector offset )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
Deprecated ( "llMakeFire" ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public void llRezAtRoot ( string inventory , LSL_Vector pos , LSL_Vector vel , LSL_Rotation rot , int param )
{
m_host . AddScriptLPS ( 1 ) ;
2012-07-04 21:21:47 +00:00
Util . FireAndForget ( x = >
2012-03-09 00:57:49 +00:00
{
if ( Double . IsNaN ( rot . x ) | | Double . IsNaN ( rot . y ) | | Double . IsNaN ( rot . z ) | | Double . IsNaN ( rot . s ) )
return ;
2012-07-04 21:21:47 +00:00
2012-03-09 00:57:49 +00:00
float dist = ( float ) llVecDist ( llGetPos ( ) , pos ) ;
2008-09-26 02:51:00 +00:00
2012-03-09 00:57:49 +00:00
if ( dist > m_ScriptDistanceFactor * 10.0f )
return ;
2009-07-28 09:40:07 +00:00
2012-07-04 21:21:47 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( inventory ) ;
2008-09-26 02:51:00 +00:00
2012-07-04 21:21:47 +00:00
if ( item = = null )
2008-09-26 02:51:00 +00:00
{
2012-07-04 21:21:47 +00:00
llSay ( 0 , "Could not find object " + inventory ) ;
return ;
}
2008-09-26 02:51:00 +00:00
2012-07-04 21:21:47 +00:00
if ( item . InvType ! = ( int ) InventoryType . Object )
{
llSay ( 0 , "Unable to create requested object. Object is missing from database." ) ;
return ;
}
2008-09-26 02:51:00 +00:00
2012-07-04 21:21:47 +00:00
// need the magnitude later
// float velmag = (float)Util.GetMagnitude(llvel);
2008-09-26 02:51:00 +00:00
2012-08-18 14:18:31 +00:00
SceneObjectGroup new_group = World . RezObject ( m_host , item , pos , rot , vel , param ) ;
2008-09-26 02:51:00 +00:00
2012-07-04 21:21:47 +00:00
// If either of these are null, then there was an unknown error.
if ( new_group = = null )
return ;
2008-09-26 02:51:00 +00:00
2012-07-04 21:21:47 +00:00
// objects rezzed with this method are die_at_edge by default.
new_group . RootPart . SetDieAtEdge ( true ) ;
2010-06-12 05:13:27 +00:00
2012-07-04 21:21:47 +00:00
new_group . ResumeScripts ( ) ;
2008-09-26 02:51:00 +00:00
2012-07-04 21:21:47 +00:00
m_ScriptEngine . PostObjectEvent ( m_host . LocalId , new EventParams (
"object_rez" , new Object [ ] {
new LSL_String (
new_group . RootPart . UUID . ToString ( ) ) } ,
new DetectParams [ 0 ] ) ) ;
2008-09-26 02:51:00 +00:00
2012-07-04 21:21:47 +00:00
float groupmass = new_group . GetMass ( ) ;
2012-04-03 05:01:05 +00:00
2012-07-04 21:21:47 +00:00
PhysicsActor pa = new_group . RootPart . PhysActor ;
2009-07-28 09:40:07 +00:00
2012-08-18 00:17:01 +00:00
if ( pa ! = null & & pa . IsPhysical & & ( Vector3 ) vel ! = Vector3 . Zero )
2012-07-04 21:21:47 +00:00
{
//Recoil.
2012-08-18 00:17:01 +00:00
llApplyImpulse ( vel * groupmass , 0 ) ;
2012-07-04 21:21:47 +00:00
}
// Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2012-03-09 00:57:49 +00:00
} ) ;
//ScriptSleep((int)((groupmass * velmag) / 10));
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public void llRezObject ( string inventory , LSL_Vector pos , LSL_Vector vel , LSL_Rotation rot , int param )
{
llRezAtRoot ( inventory , pos , vel , rot , param ) ;
}
public void llLookAt ( LSL_Vector target , double strength , double damping )
{
2009-07-28 09:40:07 +00:00
m_host . AddScriptLPS ( 1 ) ;
// Determine where we are looking from
LSL_Vector from = llGetPos ( ) ;
// Work out the normalised vector from the source to the target
LSL_Vector delta = llVecNorm ( target - from ) ;
LSL_Vector angle = new LSL_Vector ( 0 , 0 , 0 ) ;
// Calculate the yaw
// subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system
angle . x = llAtan2 ( delta . z , delta . y ) - ScriptBaseClass . PI_BY_TWO ;
// Calculate pitch
angle . y = llAtan2 ( delta . x , llSqrt ( ( delta . y * delta . y ) + ( delta . z * delta . z ) ) ) ;
2009-02-09 10:04:54 +00:00
// we need to convert from a vector describing
// the angles of rotation in radians into rotation value
2012-01-13 19:37:17 +00:00
LSL_Rotation rot = llEuler2Rot ( angle ) ;
// Per discussion with Melanie, for non-physical objects llLookAt appears to simply
// set the rotation of the object, copy that behavior
2012-04-03 05:01:05 +00:00
PhysicsActor pa = m_host . PhysActor ;
if ( strength = = 0 | | pa = = null | | ! pa . IsPhysical )
2012-01-13 19:37:17 +00:00
{
llSetRot ( rot ) ;
}
else
{
2012-08-18 14:18:31 +00:00
m_host . StartLookAt ( rot , ( float ) strength , ( float ) damping ) ;
2012-01-13 19:37:17 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llStopLookAt ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-12-22 00:26:12 +00:00
// NotImplemented("llStopLookAt");
m_host . StopLookAt ( ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetTimerEvent ( double sec )
{
2008-11-12 11:02:55 +00:00
if ( sec ! = 0.0 & & sec < m_MinTimerInterval )
2008-11-10 05:33:36 +00:00
sec = m_MinTimerInterval ;
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
// Setting timer repeat
2012-05-08 22:20:27 +00:00
AsyncCommands . TimerPlugin . SetTimerEvent ( m_host . LocalId , m_item . ItemID , sec ) ;
2008-09-26 02:51:00 +00:00
}
2009-07-06 13:09:03 +00:00
public virtual void llSleep ( double sec )
2008-09-26 02:51:00 +00:00
{
2012-05-13 20:58:47 +00:00
// m_log.Info("llSleep snoozing " + sec + "s.");
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
Thread . Sleep ( ( int ) ( sec * 1000 ) ) ;
}
public LSL_Float llGetMass ( )
{
m_host . AddScriptLPS ( 1 ) ;
2012-04-06 20:14:19 +00:00
if ( m_host . ParentGroup . IsAttachment )
{
ScenePresence attachedAvatar = World . GetScenePresence ( m_host . ParentGroup . AttachedAvatar ) ;
if ( attachedAvatar ! = null )
{
return attachedAvatar . GetMass ( ) ;
}
else
{
return 0 ;
}
}
2012-04-06 19:32:39 +00:00
else
2012-04-06 20:14:19 +00:00
{
if ( m_host . IsRoot )
{
return m_host . ParentGroup . GetMass ( ) ;
}
else
{
return m_host . GetMass ( ) ;
}
}
2008-09-26 02:51:00 +00:00
}
public void llCollisionFilter ( string name , string id , int accept )
{
m_host . AddScriptLPS ( 1 ) ;
2009-12-31 17:41:07 +00:00
m_host . CollisionFilter . Clear ( ) ;
2012-05-15 00:02:38 +00:00
UUID objectID ;
if ( ! UUID . TryParse ( id , out objectID ) )
objectID = UUID . Zero ;
if ( objectID = = UUID . Zero & & name = = "" )
return ;
m_host . CollisionFilter . Add ( accept , objectID . ToString ( ) + name ) ;
2008-09-26 02:51:00 +00:00
}
public void llTakeControls ( int controls , int accept , int pass_on )
{
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter ! = UUID . Zero )
2008-09-26 02:51:00 +00:00
{
2012-05-08 21:58:34 +00:00
ScenePresence presence = World . GetScenePresence ( m_item . PermsGranter ) ;
2008-09-26 02:51:00 +00:00
if ( presence ! = null )
{
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_TAKE_CONTROLS ) ! = 0 )
2008-09-26 02:51:00 +00:00
{
2012-05-08 22:20:27 +00:00
presence . RegisterControlEventsToScript ( controls , accept , pass_on , m_host . LocalId , m_item . ItemID ) ;
2008-09-26 02:51:00 +00:00
}
}
}
m_host . AddScriptLPS ( 1 ) ;
}
public void llReleaseControls ( )
2009-07-28 09:40:07 +00:00
{
2009-02-20 14:04:29 +00:00
m_host . AddScriptLPS ( 1 ) ;
2008-09-26 02:51:00 +00:00
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter ! = UUID . Zero )
2008-09-26 02:51:00 +00:00
{
2012-05-08 21:58:34 +00:00
ScenePresence presence = World . GetScenePresence ( m_item . PermsGranter ) ;
2008-09-26 02:51:00 +00:00
if ( presence ! = null )
{
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_TAKE_CONTROLS ) ! = 0 )
2008-09-26 02:51:00 +00:00
{
// Unregister controls from Presence
2012-05-08 22:20:27 +00:00
presence . UnRegisterControlEventsToScript ( m_host . LocalId , m_item . ItemID ) ;
2008-09-26 02:51:00 +00:00
// Remove Take Control permission.
2012-05-08 21:58:34 +00:00
m_item . PermsMask & = ~ ScriptBaseClass . PERMISSION_TAKE_CONTROLS ;
2008-09-26 02:51:00 +00:00
}
}
}
}
2009-05-13 01:13:59 +00:00
public void llReleaseURL ( string url )
{
m_host . AddScriptLPS ( 1 ) ;
2009-05-13 03:09:30 +00:00
if ( m_UrlModule ! = null )
m_UrlModule . ReleaseURL ( url ) ;
2009-05-13 01:13:59 +00:00
}
2012-04-23 23:03:57 +00:00
/// <summary>
/// Attach the object containing this script to the avatar that owns it.
/// </summary>
/// <param name='attachment'>The attachment point (e.g. ATTACH_CHEST)</param>
/// <returns>true if the attach suceeded, false if it did not</returns>
public bool AttachToAvatar ( int attachmentPoint )
{
SceneObjectGroup grp = m_host . ParentGroup ;
ScenePresence presence = World . GetScenePresence ( m_host . OwnerID ) ;
IAttachmentsModule attachmentsModule = m_ScriptEngine . World . AttachmentsModule ;
if ( attachmentsModule ! = null )
2012-08-13 23:12:15 +00:00
return attachmentsModule . AttachObject ( presence , grp , ( uint ) attachmentPoint , false , false ) ;
2012-04-23 23:03:57 +00:00
else
return false ;
}
/// <summary>
/// Detach the object containing this script from the avatar it is attached to.
/// </summary>
/// <remarks>
/// Nothing happens if the object is not attached.
/// </remarks>
public void DetachFromAvatar ( )
{
Util . FireAndForget ( DetachWrapper , m_host ) ;
}
private void DetachWrapper ( object o )
{
2012-06-28 22:31:23 +00:00
if ( World . AttachmentsModule ! = null )
{
SceneObjectPart host = ( SceneObjectPart ) o ;
ScenePresence presence = World . GetScenePresence ( host . OwnerID ) ;
World . AttachmentsModule . DetachSingleAttachmentToInv ( presence , host . ParentGroup ) ;
}
2012-04-23 23:03:57 +00:00
}
public void llAttachToAvatar ( int attachmentPoint )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2009-05-13 02:21:21 +00:00
2011-08-24 19:49:23 +00:00
// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
// return;
2009-05-13 02:21:21 +00:00
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter ! = m_host . OwnerID )
2009-05-13 02:21:21 +00:00
return ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_ATTACH ) ! = 0 )
2012-04-23 23:03:57 +00:00
AttachToAvatar ( attachmentPoint ) ;
2008-09-26 02:51:00 +00:00
}
public void llDetachFromAvatar ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-05-13 02:06:12 +00:00
2011-08-26 23:15:21 +00:00
if ( m_host . ParentGroup . AttachmentPoint = = 0 )
2009-05-13 02:06:12 +00:00
return ;
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter ! = m_host . OwnerID )
2009-05-13 02:06:12 +00:00
return ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_ATTACH ) ! = 0 )
2012-04-23 23:03:57 +00:00
DetachFromAvatar ( ) ;
2010-11-16 00:37:44 +00:00
}
2008-09-26 02:51:00 +00:00
public void llTakeCamera ( string avatar )
{
m_host . AddScriptLPS ( 1 ) ;
Deprecated ( "llTakeCamera" ) ;
}
public void llReleaseCamera ( string avatar )
{
m_host . AddScriptLPS ( 1 ) ;
Deprecated ( "llReleaseCamera" ) ;
}
public LSL_String llGetOwner ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-10-15 23:35:27 +00:00
return m_host . OwnerID . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public void llInstantMessage ( string user , string message )
{
m_host . AddScriptLPS ( 1 ) ;
// 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,
// but I don't think we have a list of scenes available from here.
// (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
// user is a UUID
// 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 . UUID . ToString ( ) ) ; // fromAgentID.Guid;
msg . toAgentID = new Guid ( user ) ; // toAgentID.Guid;
msg . imSessionID = new Guid ( friendTransactionID . ToString ( ) ) ; // This is the item we're mucking with here
2009-02-22 20:52:55 +00:00
// 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());
2008-09-26 02:51:00 +00:00
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
//}
2009-03-07 14:16:26 +00:00
// Cap the message length at 1024.
if ( message ! = null & & message . Length > 1024 )
msg . message = message . Substring ( 0 , 1024 ) ;
else
msg . message = message ;
2008-09-26 02:51:00 +00:00
msg . dialog = ( byte ) 19 ; // messgage from script ??? // dialog;
msg . fromGroup = false ; // fromGroup;
msg . offline = ( byte ) 0 ; //offline;
msg . ParentEstateID = 0 ; //ParentEstateID;
2011-02-04 23:14:21 +00:00
msg . Position = new Vector3 ( m_host . AbsolutePosition ) ;
2008-09-26 02:51:00 +00:00
msg . RegionID = World . RegionInfo . RegionID . Guid ; //RegionID.Guid;
2011-02-04 23:06:24 +00:00
msg . binaryBucket
= Util . StringToBytes256 (
"{0}/{1}/{2}/{3}" ,
World . RegionInfo . RegionName ,
( int ) Math . Floor ( m_host . AbsolutePosition . X ) ,
( int ) Math . Floor ( m_host . AbsolutePosition . Y ) ,
( int ) Math . Floor ( m_host . AbsolutePosition . Z ) ) ;
2008-11-16 04:31:52 +00:00
2008-12-14 22:27:40 +00:00
if ( m_TransferModule ! = null )
2008-11-16 04:31:52 +00:00
{
2009-06-10 04:28:56 +00:00
m_TransferModule . SendInstantMessage ( msg , delegate ( bool success ) { } ) ;
2008-11-16 04:31:52 +00:00
}
2011-02-04 23:06:24 +00:00
2008-11-16 04:31:52 +00:00
ScriptSleep ( 2000 ) ;
2008-09-26 02:51:00 +00:00
}
public void llEmail ( string address , string subject , string message )
{
m_host . AddScriptLPS ( 1 ) ;
IEmailModule emailModule = m_ScriptEngine . World . RequestModuleInterface < IEmailModule > ( ) ;
if ( emailModule = = null )
2009-02-14 21:25:22 +00:00
{
ShoutError ( "llEmail: email module not configured" ) ;
2008-09-26 02:51:00 +00:00
return ;
2009-02-14 21:25:22 +00:00
}
2008-09-26 02:51:00 +00:00
emailModule . SendEmail ( m_host . UUID , address , subject , message ) ;
2012-05-13 20:58:47 +00:00
llSleep ( EMAIL_PAUSE_TIME ) ;
2008-09-26 02:51:00 +00:00
}
public void llGetNextEmail ( string address , string subject )
{
m_host . AddScriptLPS ( 1 ) ;
IEmailModule emailModule = m_ScriptEngine . World . RequestModuleInterface < IEmailModule > ( ) ;
if ( emailModule = = null )
2009-02-14 21:25:22 +00:00
{
ShoutError ( "llGetNextEmail: email module not configured" ) ;
2008-09-26 02:51:00 +00:00
return ;
2009-02-14 21:25:22 +00:00
}
2008-09-26 02:51:00 +00:00
Email email ;
email = emailModule . GetNextEmail ( m_host . UUID , address , subject ) ;
if ( email = = null )
return ;
m_ScriptEngine . PostObjectEvent ( m_host . LocalId ,
new EventParams ( "email" ,
new Object [ ] {
new LSL_String ( email . time ) ,
new LSL_String ( email . sender ) ,
new LSL_String ( email . subject ) ,
new LSL_String ( email . message ) ,
new LSL_Integer ( email . numLeft ) } ,
new DetectParams [ 0 ] ) ) ;
}
public LSL_String llGetKey ( )
{
m_host . AddScriptLPS ( 1 ) ;
return m_host . UUID . ToString ( ) ;
}
2012-04-24 18:38:37 +00:00
public LSL_Key llGenerateKey ( )
{
m_host . AddScriptLPS ( 1 ) ;
return UUID . Random ( ) . ToString ( ) ;
}
2008-09-26 02:51:00 +00:00
public void llSetBuoyancy ( double buoyancy )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2008-09-26 02:51:00 +00:00
{
2011-09-01 00:22:28 +00:00
m_host . ParentGroup . RootPart . SetBuoyancy ( ( float ) buoyancy ) ;
2008-09-26 02:51:00 +00:00
}
}
2009-03-06 23:01:35 +00:00
/// <summary>
/// Attempt to clamp the object on the Z axis at the given height over tau seconds.
/// </summary>
/// <param name="height">Height to hover. Height of zero disables hover.</param>
/// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param>
/// <param name="tau">Number of seconds over which to reach target</param>
2008-09-26 02:51:00 +00:00
public void llSetHoverHeight ( double height , int water , double tau )
{
m_host . AddScriptLPS ( 1 ) ;
2012-04-03 05:01:05 +00:00
2008-10-30 14:06:00 +00:00
if ( m_host . PhysActor ! = null )
{
2009-03-06 23:01:35 +00:00
PIDHoverType hoverType = PIDHoverType . Ground ;
2009-04-02 10:24:12 +00:00
if ( water ! = 0 )
2009-03-06 23:01:35 +00:00
{
hoverType = PIDHoverType . GroundAndWater ;
}
m_host . SetHoverHeight ( ( float ) height , hoverType , ( float ) tau ) ;
2008-10-30 14:06:00 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llStopHover ( )
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-30 14:06:00 +00:00
if ( m_host . PhysActor ! = null )
{
2009-03-06 23:01:35 +00:00
m_host . SetHoverHeight ( 0f , PIDHoverType . Ground , 0f ) ;
2008-10-30 14:06:00 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llMinEventDelay ( double delay )
{
m_host . AddScriptLPS ( 1 ) ;
2008-12-21 19:04:06 +00:00
try
{
2012-05-08 21:58:34 +00:00
m_ScriptEngine . SetMinEventDelay ( m_item . ItemID , delay ) ;
2008-12-21 19:04:06 +00:00
}
catch ( NotImplementedException )
{
// Currently not implemented in DotNetEngine only XEngine
NotImplemented ( "llMinEventDelay in DotNetEngine" ) ;
}
2008-09-26 02:51:00 +00:00
}
2008-09-29 20:24:59 +00:00
/// <summary>
/// llSoundPreload is deprecated. In SL this appears to do absolutely nothing
/// and is documented to have no delay.
/// </summary>
public void llSoundPreload ( string sound )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
}
public void llRotLookAt ( LSL_Rotation target , double strength , double damping )
{
m_host . AddScriptLPS ( 1 ) ;
2012-01-13 19:37:17 +00:00
// Per discussion with Melanie, for non-physical objects llLookAt appears to simply
// set the rotation of the object, copy that behavior
2012-04-03 05:01:05 +00:00
PhysicsActor pa = m_host . PhysActor ;
if ( strength = = 0 | | pa = = null | | ! pa . IsPhysical )
2012-01-13 19:37:17 +00:00
{
llSetLocalRot ( target ) ;
}
else
{
2012-08-18 14:18:31 +00:00
m_host . RotLookAt ( target , ( float ) strength , ( float ) damping ) ;
2012-01-13 19:37:17 +00:00
}
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llStringLength ( string str )
{
m_host . AddScriptLPS ( 1 ) ;
if ( str . Length > 0 )
{
return str . Length ;
}
else
{
return 0 ;
}
}
public void llStartAnimation ( string anim )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter = = UUID . Zero )
2008-09-26 02:51:00 +00:00
return ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_TRIGGER_ANIMATION ) ! = 0 )
2008-09-26 02:51:00 +00:00
{
2012-05-08 21:58:34 +00:00
ScenePresence presence = World . GetScenePresence ( m_item . PermsGranter ) ;
2008-09-26 02:51:00 +00:00
if ( presence ! = null )
{
// Do NOT try to parse UUID, animations cannot be triggered by ID
2009-11-17 15:05:40 +00:00
UUID animID = InventoryKey ( anim , ( int ) AssetType . Animation ) ;
2008-09-26 02:51:00 +00:00
if ( animID = = UUID . Zero )
2009-11-17 15:05:40 +00:00
presence . Animator . AddAnimation ( anim , m_host . UUID ) ;
2008-09-26 02:51:00 +00:00
else
2009-11-17 15:05:40 +00:00
presence . Animator . AddAnimation ( animID , m_host . UUID ) ;
2008-09-26 02:51:00 +00:00
}
}
}
public void llStopAnimation ( string anim )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter = = UUID . Zero )
2008-09-26 02:51:00 +00:00
return ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_TRIGGER_ANIMATION ) ! = 0 )
2008-09-26 02:51:00 +00:00
{
2012-05-08 21:58:34 +00:00
ScenePresence presence = World . GetScenePresence ( m_item . PermsGranter ) ;
2008-09-26 02:51:00 +00:00
if ( presence ! = null )
{
2012-05-25 23:36:01 +00:00
UUID animID = KeyOrName ( anim ) ;
2008-09-26 02:51:00 +00:00
if ( animID = = UUID . Zero )
2009-11-17 15:05:40 +00:00
presence . Animator . RemoveAnimation ( anim ) ;
2008-09-26 02:51:00 +00:00
else
2009-11-17 15:05:40 +00:00
presence . Animator . RemoveAnimation ( animID ) ;
2008-09-26 02:51:00 +00:00
}
}
}
2008-09-30 01:59:51 +00:00
public void llPointAt ( LSL_Vector pos )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
}
public void llStopPointAt ( )
{
m_host . AddScriptLPS ( 1 ) ;
}
public void llTargetOmega ( LSL_Vector axis , double spinrate , double gain )
{
m_host . AddScriptLPS ( 1 ) ;
2011-10-26 12:33:52 +00:00
TargetOmega ( m_host , axis , spinrate , gain ) ;
2008-09-26 02:51:00 +00:00
}
2011-10-26 12:33:52 +00:00
protected void TargetOmega ( SceneObjectPart part , LSL_Vector axis , double spinrate , double gain )
{
2012-08-18 00:17:01 +00:00
part . UpdateAngularVelocity ( axis * spinrate ) ;
2011-10-26 12:33:52 +00:00
}
2008-09-26 02:51:00 +00:00
public LSL_Integer llGetStartParameter ( )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
return m_ScriptEngine . GetStartParameter ( m_item . ItemID ) ;
2008-09-26 02:51:00 +00:00
}
public void llRequestPermissions ( string agent , int perm )
{
2012-04-23 21:23:47 +00:00
UUID agentID ;
2008-09-26 02:51:00 +00:00
if ( ! UUID . TryParse ( agent , out agentID ) )
return ;
if ( agentID = = UUID . Zero | | perm = = 0 ) // Releasing permissions
{
llReleaseControls ( ) ;
2012-05-08 21:58:34 +00:00
m_item . PermsGranter = UUID . Zero ;
m_item . PermsMask = 0 ;
2008-09-26 02:51:00 +00:00
2012-05-08 21:58:34 +00:00
m_ScriptEngine . PostScriptEvent ( m_item . ItemID , new EventParams (
2008-09-26 02:51:00 +00:00
"run_time_permissions" , new Object [ ] {
new LSL_Integer ( 0 ) } ,
new DetectParams [ 0 ] ) ) ;
return ;
}
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter ! = agentID | | ( perm & ScriptBaseClass . PERMISSION_TAKE_CONTROLS ) = = 0 )
2008-09-26 02:51:00 +00:00
llReleaseControls ( ) ;
m_host . AddScriptLPS ( 1 ) ;
2012-08-15 16:22:52 +00:00
int implicitPerms = 0 ;
2011-08-26 22:06:41 +00:00
if ( m_host . ParentGroup . IsAttachment & & ( UUID ) agent = = m_host . ParentGroup . AttachedAvatar )
2008-09-26 02:51:00 +00:00
{
// When attached, certain permissions are implicit if requested from owner
2012-08-15 16:22:52 +00:00
implicitPerms = ScriptBaseClass . PERMISSION_TAKE_CONTROLS |
2008-09-26 02:51:00 +00:00
ScriptBaseClass . PERMISSION_TRIGGER_ANIMATION |
ScriptBaseClass . PERMISSION_CONTROL_CAMERA |
ScriptBaseClass . PERMISSION_ATTACH ;
2012-08-15 16:22:52 +00:00
}
else
{
bool sitting = false ;
if ( m_host . SitTargetAvatar = = agentID )
{
sitting = true ;
}
else
2008-09-26 02:51:00 +00:00
{
2012-08-15 16:22:52 +00:00
foreach ( SceneObjectPart p in m_host . ParentGroup . Parts )
2009-02-20 14:04:29 +00:00
{
2012-08-15 16:22:52 +00:00
if ( p . SitTargetAvatar = = agentID )
sitting = true ;
2009-02-20 14:04:29 +00:00
}
2012-08-15 16:22:52 +00:00
}
2008-09-26 02:51:00 +00:00
2012-08-15 16:22:52 +00:00
if ( sitting )
{
// When agent is sitting, certain permissions are implicit if requested from sitting agent
implicitPerms = ScriptBaseClass . PERMISSION_TRIGGER_ANIMATION |
ScriptBaseClass . PERMISSION_CONTROL_CAMERA |
ScriptBaseClass . PERMISSION_TRACK_CAMERA |
ScriptBaseClass . PERMISSION_TAKE_CONTROLS ;
}
else
{
if ( World . GetExtraSetting ( "auto_grant_attach_perms" ) = = "true" )
implicitPerms = ScriptBaseClass . PERMISSION_ATTACH ;
2008-09-26 02:51:00 +00:00
}
}
2012-08-15 16:22:52 +00:00
if ( ( perm & ( ~ implicitPerms ) ) = = 0 ) // Requested only implicit perms
{
lock ( m_host . TaskInventory )
2008-09-26 02:51:00 +00:00
{
2012-08-15 16:22:52 +00:00
m_host . TaskInventory [ m_item . ItemID ] . PermsGranter = agentID ;
m_host . TaskInventory [ m_item . ItemID ] . PermsMask = perm ;
}
2008-09-26 02:51:00 +00:00
2012-08-15 16:22:52 +00:00
m_ScriptEngine . PostScriptEvent ( m_item . ItemID , new EventParams (
"run_time_permissions" , new Object [ ] {
new LSL_Integer ( perm ) } ,
new DetectParams [ 0 ] ) ) ;
2008-09-26 02:51:00 +00:00
2012-08-15 16:22:52 +00:00
return ;
2008-09-26 02:51:00 +00:00
}
ScenePresence presence = World . GetScenePresence ( agentID ) ;
if ( presence ! = null )
{
2012-05-22 22:06:40 +00:00
// If permissions are being requested from an NPC and were not implicitly granted above then
// auto grant all reuqested permissions if the script is owned by the NPC or the NPCs owner
INPCModule npcModule = World . RequestModuleInterface < INPCModule > ( ) ;
if ( npcModule ! = null & & npcModule . IsNPC ( agentID , World ) )
{
if ( agentID = = m_host . ParentGroup . OwnerID | | npcModule . GetOwner ( agentID ) = = m_host . ParentGroup . OwnerID )
{
lock ( m_host . TaskInventory )
{
m_host . TaskInventory [ m_item . ItemID ] . PermsGranter = agentID ;
m_host . TaskInventory [ m_item . ItemID ] . PermsMask = perm ;
}
2012-05-26 01:14:32 +00:00
m_ScriptEngine . PostScriptEvent (
m_item . ItemID ,
new EventParams (
"run_time_permissions" , new Object [ ] { new LSL_Integer ( perm ) } , new DetectParams [ 0 ] ) ) ;
2012-05-22 22:06:40 +00:00
}
2012-05-26 01:14:32 +00:00
2012-05-22 22:06:40 +00:00
// it is an NPC, exit even if the permissions werent granted above, they are not going to answer
// the question!
return ;
}
2009-02-20 14:04:29 +00:00
string ownerName = resolveName ( m_host . ParentGroup . RootPart . OwnerID ) ;
2008-09-26 02:51:00 +00:00
if ( ownerName = = String . Empty )
2009-02-20 14:04:29 +00:00
ownerName = "(hippos)" ;
2008-09-26 02:51:00 +00:00
if ( ! m_waitingForScriptAnswer )
{
2009-02-20 14:04:29 +00:00
lock ( m_host . TaskInventory )
{
2012-05-08 21:58:34 +00:00
m_host . TaskInventory [ m_item . ItemID ] . PermsGranter = agentID ;
m_host . TaskInventory [ m_item . ItemID ] . PermsMask = 0 ;
2009-02-20 14:04:29 +00:00
}
2009-07-28 09:40:07 +00:00
2009-02-20 14:04:29 +00:00
presence . ControllingClient . OnScriptAnswer + = handleScriptAnswer ;
2008-09-26 02:51:00 +00:00
m_waitingForScriptAnswer = true ;
}
2009-02-20 14:04:29 +00:00
presence . ControllingClient . SendScriptQuestion (
2012-05-08 21:58:34 +00:00
m_host . UUID , m_host . ParentGroup . RootPart . Name , ownerName , m_item . ItemID , perm ) ;
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
return ;
}
// Requested agent is not in range, refuse perms
2012-05-26 01:14:32 +00:00
m_ScriptEngine . PostScriptEvent (
m_item . ItemID ,
new EventParams ( "run_time_permissions" , new Object [ ] { new LSL_Integer ( 0 ) } , new DetectParams [ 0 ] ) ) ;
2008-09-26 02:51:00 +00:00
}
void handleScriptAnswer ( IClientAPI client , UUID taskID , UUID itemID , int answer )
{
if ( taskID ! = m_host . UUID )
return ;
2012-04-23 21:23:47 +00:00
client . OnScriptAnswer - = handleScriptAnswer ;
m_waitingForScriptAnswer = false ;
2008-09-26 02:51:00 +00:00
if ( ( answer & ScriptBaseClass . PERMISSION_TAKE_CONTROLS ) = = 0 )
llReleaseControls ( ) ;
2009-07-28 09:40:07 +00:00
2009-02-20 14:04:29 +00:00
lock ( m_host . TaskInventory )
{
2012-05-08 21:58:34 +00:00
m_host . TaskInventory [ m_item . ItemID ] . PermsMask = answer ;
2009-02-20 14:04:29 +00:00
}
2008-09-26 02:51:00 +00:00
2012-05-26 01:14:32 +00:00
m_ScriptEngine . PostScriptEvent (
m_item . ItemID ,
new EventParams ( "run_time_permissions" , new Object [ ] { new LSL_Integer ( answer ) } , new DetectParams [ 0 ] ) ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetPermissionsKey ( )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
return m_item . PermsGranter . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llGetPermissions ( )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
int perms = m_item . PermsMask ;
2008-09-26 02:51:00 +00:00
2012-04-23 21:52:46 +00:00
if ( m_automaticLinkPermission )
perms | = ScriptBaseClass . PERMISSION_CHANGE_LINKS ;
return perms ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llGetLinkNumber ( )
{
m_host . AddScriptLPS ( 1 ) ;
2010-08-25 23:08:53 +00:00
if ( m_host . ParentGroup . PrimCount > 1 )
2008-09-26 02:51:00 +00:00
{
return m_host . LinkNum ;
}
else
{
return 0 ;
}
}
public void llSetLinkColor ( int linknumber , LSL_Vector color , int face )
{
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
foreach ( SceneObjectPart part in parts )
2012-08-20 08:31:29 +00:00
part . SetFaceColorAlpha ( face , color , null ) ;
2008-09-26 02:51:00 +00:00
}
public void llCreateLink ( string target , int parent )
{
m_host . AddScriptLPS ( 1 ) ;
2010-08-18 18:17:20 +00:00
UUID targetID ;
if ( ! UUID . TryParse ( target , out targetID ) )
return ;
2009-07-28 09:40:07 +00:00
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_CHANGE_LINKS ) = = 0
2009-07-28 09:40:07 +00:00
& & ! m_automaticLinkPermission )
2008-12-11 02:35:51 +00:00
{
ShoutError ( "Script trying to link but PERMISSION_CHANGE_LINKS permission not set!" ) ;
return ;
2008-09-26 02:51:00 +00:00
}
2008-12-11 02:35:51 +00:00
2008-12-03 10:10:01 +00:00
IClientAPI client = null ;
2012-05-08 21:58:34 +00:00
ScenePresence sp = World . GetScenePresence ( m_item . PermsGranter ) ;
2008-12-03 23:48:24 +00:00
if ( sp ! = null )
client = sp . ControllingClient ;
2009-07-28 09:40:07 +00:00
2010-08-18 18:17:20 +00:00
SceneObjectPart targetPart = World . GetSceneObjectPart ( ( UUID ) targetID ) ;
2009-07-28 09:40:07 +00:00
2011-08-26 23:15:21 +00:00
if ( targetPart . ParentGroup . AttachmentPoint ! = 0 )
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
return ; // Fail silently if attached
2012-04-25 18:09:22 +00:00
if ( targetPart . ParentGroup . RootPart . OwnerID ! = m_host . ParentGroup . RootPart . OwnerID )
return ;
2008-09-26 02:51:00 +00:00
SceneObjectGroup parentPrim = null , childPrim = null ;
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
if ( targetPart ! = null )
{
2012-04-25 18:09:22 +00:00
if ( parent ! = 0 )
{
2008-09-26 02:51:00 +00:00
parentPrim = m_host . ParentGroup ;
childPrim = targetPart . ParentGroup ;
}
else
{
parentPrim = targetPart . ParentGroup ;
childPrim = m_host . ParentGroup ;
}
2011-11-02 21:59:00 +00:00
// Required for linking
childPrim . RootPart . ClearUpdateSchedule ( ) ;
2012-04-25 18:09:22 +00:00
parentPrim . LinkToGroup ( childPrim , true ) ;
2008-09-26 02:51:00 +00:00
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
parentPrim . TriggerScriptChangedEvent ( Changed . LINK ) ;
2010-05-31 17:00:02 +00:00
parentPrim . RootPart . CreateSelected = true ;
2008-09-26 02:51:00 +00:00
parentPrim . HasGroupChanged = true ;
parentPrim . ScheduleGroupForFullUpdate ( ) ;
2009-07-28 09:40:07 +00:00
2008-12-11 02:35:51 +00:00
if ( client ! = null )
2011-09-15 17:58:58 +00:00
parentPrim . SendPropertiesToClient ( client ) ;
2008-09-26 02:51:00 +00:00
ScriptSleep ( 1000 ) ;
}
public void llBreakLink ( int linknum )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_CHANGE_LINKS ) = = 0
2012-04-23 21:52:46 +00:00
& & ! m_automaticLinkPermission )
2008-09-26 02:51:00 +00:00
{
2012-04-23 21:52:46 +00:00
ShoutError ( "Script trying to link but PERMISSION_CHANGE_LINKS permission not set!" ) ;
return ;
2008-09-26 02:51:00 +00:00
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
if ( linknum < ScriptBaseClass . LINK_THIS )
2009-02-20 14:04:29 +00:00
return ;
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
SceneObjectGroup parentPrim = m_host . ParentGroup ;
2009-07-28 09:40:07 +00:00
2011-08-26 23:15:21 +00:00
if ( parentPrim . AttachmentPoint ! = 0 )
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
return ; // Fail silently if attached
2008-09-26 02:51:00 +00:00
SceneObjectPart childPrim = null ;
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
switch ( linknum )
{
case ScriptBaseClass . LINK_ROOT :
break ;
case ScriptBaseClass . LINK_SET :
case ScriptBaseClass . LINK_ALL_OTHERS :
case ScriptBaseClass . LINK_ALL_CHILDREN :
case ScriptBaseClass . LINK_THIS :
2010-09-17 00:30:46 +00:00
foreach ( SceneObjectPart part in parentPrim . Parts )
2008-09-26 02:51:00 +00:00
{
2010-09-17 00:30:46 +00:00
if ( part . UUID ! = m_host . UUID )
2008-09-26 02:51:00 +00:00
{
2010-09-17 00:30:46 +00:00
childPrim = part ;
break ;
2008-09-26 02:51:00 +00:00
}
}
2010-09-17 00:30:46 +00:00
break ;
2008-09-26 02:51:00 +00:00
default :
childPrim = parentPrim . GetLinkNumPart ( linknum ) ;
if ( childPrim . UUID = = m_host . UUID )
childPrim = null ;
break ;
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
if ( linknum = = ScriptBaseClass . LINK_ROOT )
{
// Restructuring Multiple Prims.
2010-09-17 00:30:46 +00:00
List < SceneObjectPart > parts = new List < SceneObjectPart > ( parentPrim . Parts ) ;
parts . Remove ( parentPrim . RootPart ) ;
foreach ( SceneObjectPart part in parts )
{
parentPrim . DelinkFromGroup ( part . LocalId , true ) ;
}
parentPrim . HasGroupChanged = true ;
parentPrim . ScheduleGroupForFullUpdate ( ) ;
parentPrim . TriggerScriptChangedEvent ( Changed . LINK ) ;
if ( parts . Count > 0 )
2008-09-26 02:51:00 +00:00
{
2010-09-17 00:30:46 +00:00
SceneObjectPart newRoot = parts [ 0 ] ;
parts . Remove ( newRoot ) ;
2008-09-26 02:51:00 +00:00
foreach ( SceneObjectPart part in parts )
{
2011-11-02 21:59:00 +00:00
// Required for linking
part . ClearUpdateSchedule ( ) ;
2010-09-17 00:30:46 +00:00
newRoot . ParentGroup . LinkToGroup ( part . ParentGroup ) ;
2008-09-26 02:51:00 +00:00
}
2010-09-17 00:30:46 +00:00
newRoot . ParentGroup . HasGroupChanged = true ;
newRoot . ParentGroup . ScheduleGroupForFullUpdate ( ) ;
2008-09-26 02:51:00 +00:00
}
}
else
{
if ( childPrim = = null )
return ;
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
parentPrim . DelinkFromGroup ( childPrim . LocalId , true ) ;
2009-12-06 00:02:24 +00:00
parentPrim . HasGroupChanged = true ;
parentPrim . ScheduleGroupForFullUpdate ( ) ;
2008-09-26 02:51:00 +00:00
parentPrim . TriggerScriptChangedEvent ( Changed . LINK ) ;
}
}
public void llBreakAllLinks ( )
{
m_host . AddScriptLPS ( 1 ) ;
SceneObjectGroup parentPrim = m_host . ParentGroup ;
2011-08-26 23:15:21 +00:00
if ( parentPrim . AttachmentPoint ! = 0 )
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
return ; // Fail silently if attached
2009-07-28 09:40:07 +00:00
2010-09-17 00:30:46 +00:00
List < SceneObjectPart > parts = new List < SceneObjectPart > ( parentPrim . Parts ) ;
parts . Remove ( parentPrim . RootPart ) ;
foreach ( SceneObjectPart part in parts )
2008-09-26 02:51:00 +00:00
{
2010-09-17 00:30:46 +00:00
parentPrim . DelinkFromGroup ( part . LocalId , true ) ;
parentPrim . TriggerScriptChangedEvent ( Changed . LINK ) ;
2008-09-26 02:51:00 +00:00
}
2010-09-17 00:30:46 +00:00
parentPrim . HasGroupChanged = true ;
parentPrim . ScheduleGroupForFullUpdate ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetLinkKey ( int linknum )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-29 19:57:08 +00:00
List < UUID > keytable = new List < UUID > ( ) ;
// parse for sitting avatare-uuids
2011-11-04 00:53:51 +00:00
World . ForEachRootScenePresence ( delegate ( ScenePresence presence )
2011-09-29 19:57:08 +00:00
{
2012-03-31 00:45:37 +00:00
if ( presence . ParentID ! = 0 & & m_host . ParentGroup . ContainsPart ( presence . ParentID ) )
2011-09-29 19:57:08 +00:00
keytable . Add ( presence . UUID ) ;
} ) ;
int totalprims = m_host . ParentGroup . PrimCount + keytable . Count ;
if ( linknum > m_host . ParentGroup . PrimCount & & linknum < = totalprims )
{
return keytable [ totalprims - linknum ] . ToString ( ) ;
}
if ( linknum = = 1 & & m_host . ParentGroup . PrimCount = = 1 & & keytable . Count = = 1 )
{
return m_host . UUID . ToString ( ) ;
}
2008-09-26 02:51:00 +00:00
SceneObjectPart part = m_host . ParentGroup . GetLinkNumPart ( linknum ) ;
if ( part ! = null )
{
return part . UUID . ToString ( ) ;
}
else
{
return UUID . Zero . ToString ( ) ;
}
}
2008-09-28 01:12:57 +00:00
/// <summary>
/// The rules governing the returned name are not simple. The only
/// time a blank name is returned is if the target prim has a blank
/// name. If no prim with the given link number can be found then
/// usually NULL_KEY is returned but there are exceptions.
2009-07-28 09:40:07 +00:00
///
/// In a single unlinked prim, A call with 0 returns the name, all
2008-09-28 01:12:57 +00:00
/// other values for link number return NULL_KEY
///
/// In link sets it is more complicated.
2009-07-28 09:40:07 +00:00
///
2008-09-28 01:12:57 +00:00
/// If the script is in the root prim:-
/// A zero link number returns NULL_KEY.
2009-07-28 09:40:07 +00:00
/// Positive link numbers return the name of the prim, or NULL_KEY
2008-09-28 01:12:57 +00:00
/// if a prim does not exist at that position.
/// Negative link numbers return the name of the first child prim.
2009-07-28 09:40:07 +00:00
///
2008-09-28 01:12:57 +00:00
/// If the script is in a child prim:-
/// Link numbers 0 or 1 return the name of the root prim.
/// Positive link numbers return the name of the prim or NULL_KEY
/// if a prim does not exist at that position.
/// Negative numbers return the name of the root prim.
2009-07-28 09:40:07 +00:00
///
2008-09-28 01:12:57 +00:00
/// References
/// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName
/// Mentions NULL_KEY being returned
/// http://wiki.secondlife.com/wiki/LlGetLinkName
2009-07-28 09:40:07 +00:00
/// Mentions using the LINK_* constants, some of which are negative
2008-09-28 01:12:57 +00:00
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_String llGetLinkName ( int linknum )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-29 19:57:08 +00:00
// parse for sitting avatare-names
List < String > nametable = new List < String > ( ) ;
2011-11-04 00:53:51 +00:00
World . ForEachRootScenePresence ( delegate ( ScenePresence presence )
2011-09-29 19:57:08 +00:00
{
2012-03-09 02:38:11 +00:00
SceneObjectPart sitPart = presence . ParentPart ;
2012-03-31 00:45:37 +00:00
if ( sitPart ! = null & & m_host . ParentGroup . ContainsPart ( sitPart . LocalId ) )
2011-09-29 19:57:08 +00:00
nametable . Add ( presence . ControllingClient . Name ) ;
} ) ;
int totalprims = m_host . ParentGroup . PrimCount + nametable . Count ;
if ( totalprims > m_host . ParentGroup . PrimCount )
{
// sitting Avatar-Name with negativ linknum / SinglePrim
if ( linknum < 0 & & m_host . ParentGroup . PrimCount = = 1 & & nametable . Count = = 1 )
return nametable [ 0 ] ;
// Prim-Name / SinglePrim Sitting Avatar
if ( linknum = = 1 & & m_host . ParentGroup . PrimCount = = 1 & & nametable . Count = = 1 )
return m_host . Name ;
// LinkNumber > of Real PrimSet = AvatarName
if ( linknum > m_host . ParentGroup . PrimCount & & linknum < = totalprims )
return nametable [ totalprims - linknum ] ;
}
2008-09-28 01:12:57 +00:00
// simplest case, this prims link number
if ( m_host . LinkNum = = linknum )
return m_host . Name ;
2009-07-28 09:40:07 +00:00
2008-09-28 01:12:57 +00:00
// Single prim
if ( m_host . LinkNum = = 0 )
2008-09-26 02:51:00 +00:00
{
2012-02-21 19:57:51 +00:00
if ( linknum = = 0 | | linknum = = ScriptBaseClass . LINK_ROOT )
2008-09-28 01:12:57 +00:00
return m_host . Name ;
else
return UUID . Zero . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
2011-09-29 19:57:08 +00:00
2008-09-28 01:12:57 +00:00
// Link set
SceneObjectPart part = null ;
if ( m_host . LinkNum = = 1 ) // this is the Root prim
2008-09-26 02:51:00 +00:00
{
2008-09-28 01:12:57 +00:00
if ( linknum < 0 )
part = m_host . ParentGroup . GetLinkNumPart ( 2 ) ;
else
part = m_host . ParentGroup . GetLinkNumPart ( linknum ) ;
}
else // this is a child prim
{
if ( linknum < 2 )
part = m_host . ParentGroup . GetLinkNumPart ( 1 ) ;
else
part = m_host . ParentGroup . GetLinkNumPart ( linknum ) ;
2008-09-26 02:51:00 +00:00
}
2008-09-28 01:12:57 +00:00
if ( part ! = null )
return part . Name ;
else
return UUID . Zero . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llGetInventoryNumber ( int type )
{
m_host . AddScriptLPS ( 1 ) ;
int count = 0 ;
2009-07-28 09:40:07 +00:00
2009-02-20 14:04:29 +00:00
lock ( m_host . TaskInventory )
2008-09-26 02:51:00 +00:00
{
2009-02-20 14:04:29 +00:00
foreach ( KeyValuePair < UUID , TaskInventoryItem > inv in m_host . TaskInventory )
2008-09-26 02:51:00 +00:00
{
2009-02-20 14:04:29 +00:00
if ( inv . Value . Type = = type | | type = = - 1 )
{
count = count + 1 ;
}
2008-09-26 02:51:00 +00:00
}
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
return count ;
}
public LSL_String llGetInventoryName ( int type , int number )
{
m_host . AddScriptLPS ( 1 ) ;
ArrayList keys = new ArrayList ( ) ;
2009-02-20 14:04:29 +00:00
lock ( m_host . TaskInventory )
2008-09-26 02:51:00 +00:00
{
2009-02-20 14:04:29 +00:00
foreach ( KeyValuePair < UUID , TaskInventoryItem > inv in m_host . TaskInventory )
2008-09-26 02:51:00 +00:00
{
2009-02-20 14:04:29 +00:00
if ( inv . Value . Type = = type | | type = = - 1 )
{
keys . Add ( inv . Value . Name ) ;
}
2008-09-26 02:51:00 +00:00
}
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
if ( keys . Count = = 0 )
{
return String . Empty ;
}
keys . Sort ( ) ;
if ( keys . Count > number )
{
return ( string ) keys [ number ] ;
}
return String . Empty ;
}
public LSL_Float llGetEnergy ( )
{
m_host . AddScriptLPS ( 1 ) ;
// TODO: figure out real energy value
return 1.0f ;
}
public void llGiveInventory ( string destination , string inventory )
{
m_host . AddScriptLPS ( 1 ) ;
2012-07-17 22:48:09 +00:00
2008-09-26 02:51:00 +00:00
UUID destId = UUID . Zero ;
if ( ! UUID . TryParse ( destination , out destId ) )
{
llSay ( 0 , "Could not parse key " + destination ) ;
return ;
}
2012-07-17 22:48:09 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( inventory ) ;
2008-09-26 02:51:00 +00:00
2012-07-17 22:48:09 +00:00
if ( item = = null )
2008-09-26 02:51:00 +00:00
{
llSay ( 0 , String . Format ( "Could not find object '{0}'" , inventory ) ) ;
throw new Exception ( String . Format ( "The inventory object '{0}' could not be found" , inventory ) ) ;
}
2012-07-17 22:48:09 +00:00
UUID objId = item . ItemID ;
2011-05-23 01:52:28 +00:00
// check if destination is an object
if ( World . GetSceneObjectPart ( destId ) ! = null )
2008-09-26 02:51:00 +00:00
{
2011-05-23 01:52:28 +00:00
// destination is an object
World . MoveTaskInventoryItem ( destId , m_host , objId ) ;
}
else
{
ScenePresence presence = World . GetScenePresence ( destId ) ;
if ( presence = = null )
{
UserAccount account =
World . UserAccountService . GetUserAccount (
World . RegionInfo . ScopeID ,
destId ) ;
if ( account = = null )
{
llSay ( 0 , "Can't find destination " + destId . ToString ( ) ) ;
return ;
}
}
2008-09-26 02:51:00 +00:00
// destination is an avatar
2010-08-23 22:16:48 +00:00
InventoryItemBase agentItem = World . MoveTaskInventoryItem ( destId , UUID . Zero , m_host , objId ) ;
2008-12-14 22:27:40 +00:00
if ( agentItem = = null )
return ;
if ( m_TransferModule ! = null )
2012-07-17 22:31:38 +00:00
{
2012-07-17 22:48:09 +00:00
byte [ ] bucket = new byte [ ] { ( byte ) item . Type } ;
2012-07-17 22:31:38 +00:00
GridInstantMessage msg = new GridInstantMessage ( World ,
m_host . UUID , m_host . Name + ", an object owned by " +
resolveName ( m_host . OwnerID ) + "," , destId ,
( byte ) InstantMessageDialog . TaskInventoryOffered ,
2012-07-17 22:48:09 +00:00
false , item . Name + "\n" + m_host . Name + " is located at " +
World . RegionInfo . RegionName + " " +
2012-07-17 22:31:38 +00:00
m_host . AbsolutePosition . ToString ( ) ,
agentItem . ID , true , m_host . AbsolutePosition ,
bucket ) ;
2009-06-10 04:28:56 +00:00
m_TransferModule . SendInstantMessage ( msg , delegate ( bool success ) { } ) ;
2012-07-17 22:31:38 +00:00
}
2011-05-23 01:52:28 +00:00
ScriptSleep ( 3000 ) ;
2008-09-26 02:51:00 +00:00
}
}
public void llRemoveInventory ( string name )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
2012-07-04 20:05:51 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( name ) ;
if ( item = = null )
return ;
if ( item . ItemID = = m_item . ItemID )
throw new ScriptDeleteException ( ) ;
else
m_host . Inventory . RemoveInventoryItem ( item . ItemID ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetText ( string text , LSL_Vector color , double alpha )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
Vector3 av3 = Util . Clip ( color , 0.0f , 1.0f ) ;
2012-03-01 19:18:48 +00:00
m_host . SetText ( text . Length > 254 ? text . Remove ( 254 ) : text , av3 , Util . Clip ( ( float ) alpha , 0.0f , 1.0f ) ) ;
2012-01-31 16:44:39 +00:00
//m_host.ParentGroup.HasGroupChanged = true;
//m_host.ParentGroup.ScheduleGroupForFullUpdate();
2008-09-26 02:51:00 +00:00
}
public LSL_Float llWater ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
return World . RegionInfo . RegionSettings . WaterHeight ;
}
public void llPassTouches ( int pass )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
if ( pass ! = 0 )
2009-05-27 18:01:06 +00:00
m_host . PassTouches = true ;
2009-07-28 09:40:07 +00:00
else
2009-05-27 18:01:06 +00:00
m_host . PassTouches = false ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llRequestAgentData ( string id , int data )
{
m_host . AddScriptLPS ( 1 ) ;
2008-09-26 17:25:22 +00:00
UUID uuid = ( UUID ) id ;
2010-08-05 20:50:09 +00:00
PresenceInfo pinfo = null ;
UserAccount account ;
2008-09-26 17:25:22 +00:00
2010-08-05 20:50:09 +00:00
UserInfoCacheEntry ce ;
if ( ! m_userInfoCache . TryGetValue ( uuid , out ce ) )
{
account = World . UserAccountService . GetUserAccount ( World . RegionInfo . ScopeID , uuid ) ;
if ( account = = null )
{
m_userInfoCache [ uuid ] = null ; // Cache negative
return UUID . Zero . ToString ( ) ;
}
2010-06-20 04:23:08 +00:00
2008-09-26 02:51:00 +00:00
2010-09-16 23:50:48 +00:00
PresenceInfo [ ] pinfos = World . PresenceService . GetAgents ( new string [ ] { uuid . ToString ( ) } ) ;
if ( pinfos ! = null & & pinfos . Length > 0 )
{
foreach ( PresenceInfo p in pinfos )
{
if ( p . RegionID ! = UUID . Zero )
{
pinfo = p ;
}
}
}
2010-08-05 20:50:09 +00:00
ce = new UserInfoCacheEntry ( ) ;
ce . time = Util . EnvironmentTickCount ( ) ;
ce . account = account ;
ce . pinfo = pinfo ;
}
else
{
if ( ce = = null )
return UUID . Zero . ToString ( ) ;
account = ce . account ;
pinfo = ce . pinfo ;
}
if ( Util . EnvironmentTickCount ( ) < ce . time | | ( Util . EnvironmentTickCount ( ) - ce . time ) > = 20000 )
{
2010-09-16 23:50:48 +00:00
PresenceInfo [ ] pinfos = World . PresenceService . GetAgents ( new string [ ] { uuid . ToString ( ) } ) ;
if ( pinfos ! = null & & pinfos . Length > 0 )
{
foreach ( PresenceInfo p in pinfos )
{
if ( p . RegionID ! = UUID . Zero )
{
pinfo = p ;
}
}
}
else
pinfo = null ;
2010-08-05 20:50:09 +00:00
ce . time = Util . EnvironmentTickCount ( ) ;
ce . pinfo = pinfo ;
}
2008-09-26 02:51:00 +00:00
string reply = String . Empty ;
switch ( data )
{
case 1 : // DATA_ONLINE (0|1)
2010-06-20 04:23:08 +00:00
if ( pinfo ! = null & & pinfo . RegionID ! = UUID . Zero )
2008-09-26 02:51:00 +00:00
reply = "1" ;
2010-09-24 14:26:53 +00:00
else
2008-09-26 02:51:00 +00:00
reply = "0" ;
break ;
case 2 : // DATA_NAME (First Last)
2010-01-08 18:43:34 +00:00
reply = account . FirstName + " " + account . LastName ;
2008-09-26 02:51:00 +00:00
break ;
case 3 : // DATA_BORN (YYYY-MM-DD)
DateTime born = new DateTime ( 1970 , 1 , 1 , 0 , 0 , 0 , 0 ) ;
2010-01-08 18:43:34 +00:00
born = born . AddSeconds ( account . Created ) ;
2008-09-26 02:51:00 +00:00
reply = born . ToString ( "yyyy-MM-dd" ) ;
break ;
case 4 : // DATA_RATING (0,0,0,0,0,0)
reply = "0,0,0,0,0,0" ;
break ;
2012-03-27 20:09:58 +00:00
case 7 : // DATA_USERLEVEL (integer)
reply = account . UserLevel . ToString ( ) ;
break ;
2008-09-26 02:51:00 +00:00
case 8 : // DATA_PAYINFO (0|1|2|3)
reply = "0" ;
break ;
default :
return UUID . Zero . ToString ( ) ; // Raise no event
}
UUID rq = UUID . Random ( ) ;
UUID tid = AsyncCommands .
2012-05-08 22:20:27 +00:00
DataserverPlugin . RegisterRequest ( m_host . LocalId ,
2012-05-08 21:58:34 +00:00
m_item . ItemID , rq . ToString ( ) ) ;
2008-09-26 02:51:00 +00:00
AsyncCommands .
DataserverPlugin . DataserverReply ( rq . ToString ( ) , reply ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
return tid . ToString ( ) ;
}
public LSL_String llRequestInventoryData ( string name )
{
m_host . AddScriptLPS ( 1 ) ;
2012-07-04 20:19:16 +00:00
foreach ( TaskInventoryItem item in m_host . Inventory . GetInventoryItems ( ) )
2008-09-26 02:51:00 +00:00
{
if ( item . Type = = 3 & & item . Name = = name )
{
UUID tid = AsyncCommands .
2012-05-08 22:20:27 +00:00
DataserverPlugin . RegisterRequest ( m_host . LocalId ,
2012-05-08 21:58:34 +00:00
m_item . ItemID , item . AssetID . ToString ( ) ) ;
2008-09-26 02:51:00 +00:00
Vector3 region = new Vector3 (
World . RegionInfo . RegionLocX * Constants . RegionSize ,
World . RegionInfo . RegionLocY * Constants . RegionSize ,
0 ) ;
2009-05-15 05:00:25 +00:00
World . AssetService . Get ( item . AssetID . ToString ( ) , this ,
delegate ( string i , object sender , AssetBase a )
2008-09-26 02:51:00 +00:00
{
AssetLandmark lm = new AssetLandmark ( a ) ;
float rx = ( uint ) ( lm . RegionHandle > > 32 ) ;
float ry = ( uint ) lm . RegionHandle ;
region = lm . Position + new Vector3 ( rx , ry , 0 ) - region ;
string reply = region . ToString ( ) ;
AsyncCommands .
DataserverPlugin . DataserverReply ( i . ToString ( ) ,
reply ) ;
2009-05-15 05:00:25 +00:00
} ) ;
2008-09-26 02:51:00 +00:00
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
return tid . ToString ( ) ;
}
}
2012-07-04 20:22:43 +00:00
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
return String . Empty ;
}
public void llSetDamage ( double damage )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-15 00:10:01 +00:00
m_host . ParentGroup . Damage = ( float ) damage ;
2008-09-26 02:51:00 +00:00
}
public void llTeleportAgentHome ( string agent )
{
m_host . AddScriptLPS ( 1 ) ;
UUID agentId = new UUID ( ) ;
if ( UUID . TryParse ( agent , out agentId ) )
{
ScenePresence presence = World . GetScenePresence ( agentId ) ;
if ( presence ! = null )
{
2009-07-28 09:40:07 +00:00
// agent must be over the owners land
if ( m_host . OwnerID = = World . LandChannel . GetLandObject (
2009-10-02 09:10:52 +00:00
presence . AbsolutePosition . X , presence . AbsolutePosition . Y ) . LandData . OwnerID )
2008-11-06 20:38:34 +00:00
{
2008-09-26 02:51:00 +00:00
World . TeleportClientHome ( agentId , presence . ControllingClient ) ;
2008-11-06 20:38:34 +00:00
}
2008-09-26 02:51:00 +00:00
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 5000 ) ;
2008-09-26 02:51:00 +00:00
}
2012-08-18 00:17:01 +00:00
public void llTeleportAgent ( string agent , string destination , LSL_Vector targetPos , LSL_Vector targetLookAt )
2012-06-11 15:45:52 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
UUID agentId = new UUID ( ) ;
if ( UUID . TryParse ( agent , out agentId ) )
{
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 . X , presence . AbsolutePosition . Y ) . LandData . OwnerID )
{
DoLLTeleport ( presence , destination , targetPos , targetLookAt ) ;
}
else // or must be wearing the prim
{
if ( m_host . ParentGroup . AttachmentPoint ! = 0 & & m_host . OwnerID = = presence . UUID )
{
DoLLTeleport ( presence , destination , targetPos , targetLookAt ) ;
}
}
}
}
}
2012-08-18 00:17:01 +00:00
public void llTeleportAgentGlobalCoords ( string agent , LSL_Vector global_coords , LSL_Vector targetPos , LSL_Vector targetLookAt )
2012-06-11 15:45:52 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
UUID agentId = new UUID ( ) ;
ulong regionHandle = Utils . UIntsToLong ( ( uint ) global_coords . x , ( uint ) global_coords . y ) ;
if ( UUID . TryParse ( agent , out agentId ) )
{
ScenePresence presence = World . GetScenePresence ( agentId ) ;
if ( presence ! = null & & presence . PresenceType ! = PresenceType . Npc )
{
// agent must not be a god
if ( presence . GodLevel > = 200 ) return ;
// agent must be over the owners land
if ( m_host . OwnerID = = World . LandChannel . GetLandObject (
presence . AbsolutePosition . X , presence . AbsolutePosition . Y ) . LandData . OwnerID )
{
World . RequestTeleportLocation ( presence . ControllingClient , regionHandle , targetPos , targetLookAt , ( uint ) TeleportFlags . ViaLocation ) ;
}
else // or must be wearing the prim
{
if ( m_host . ParentGroup . AttachmentPoint ! = 0 & & m_host . OwnerID = = presence . UUID )
{
World . RequestTeleportLocation ( presence . ControllingClient , regionHandle , targetPos , targetLookAt , ( uint ) TeleportFlags . ViaLocation ) ;
}
}
}
}
}
private void DoLLTeleport ( ScenePresence sp , string destination , Vector3 targetPos , Vector3 targetLookAt )
{
UUID assetID = KeyOrName ( destination ) ;
// The destinaion is not an asset ID and also doesn't name a landmark.
// Use it as a sim name
if ( assetID = = UUID . Zero )
{
World . RequestTeleportLocation ( sp . ControllingClient , destination , targetPos , targetLookAt , ( uint ) TeleportFlags . ViaLocation ) ;
return ;
}
AssetBase lma = World . AssetService . Get ( assetID . ToString ( ) ) ;
if ( lma = = null )
return ;
if ( lma . Type ! = ( sbyte ) AssetType . Landmark )
return ;
AssetLandmark lm = new AssetLandmark ( lma ) ;
World . RequestTeleportLocation ( sp . ControllingClient , lm . RegionHandle , targetPos , targetLookAt , ( uint ) TeleportFlags . ViaLocation ) ;
}
2010-03-06 20:13:12 +00:00
public void llTextBox ( string agent , string message , int chatChannel )
2008-09-26 02:51:00 +00:00
{
2010-03-06 20:13:12 +00:00
IDialogModule dm = World . RequestModuleInterface < IDialogModule > ( ) ;
if ( dm = = null )
return ;
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
2010-03-06 20:13:12 +00:00
UUID av = new UUID ( ) ;
if ( ! UUID . TryParse ( agent , out av ) )
{
LSLError ( "First parameter to llDialog needs to be a key" ) ;
return ;
}
2010-03-10 04:15:36 +00:00
if ( message = = string . Empty )
2010-03-06 20:13:12 +00:00
{
ShoutError ( "Trying to use llTextBox with empty message." ) ;
}
else if ( message . Length > 512 )
{
ShoutError ( "Trying to use llTextBox with message over 512 characters." ) ;
}
else
{
dm . SendTextBoxToUser ( av , message , chatChannel , m_host . Name , m_host . UUID , m_host . OwnerID ) ;
ScriptSleep ( 1000 ) ;
}
2008-09-26 02:51:00 +00:00
}
public void llModifyLand ( int action , int brush )
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-07 14:49:12 +00:00
ITerrainModule tm = m_ScriptEngine . World . RequestModuleInterface < ITerrainModule > ( ) ;
if ( tm ! = null )
{
2008-11-11 01:47:40 +00:00
tm . ModifyTerrain ( m_host . OwnerID , m_host . AbsolutePosition , ( byte ) brush , ( byte ) action , m_host . OwnerID ) ;
2008-10-07 14:49:12 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llCollisionSound ( string impact_sound , double impact_volume )
{
m_host . AddScriptLPS ( 1 ) ;
2011-10-03 23:37:02 +00:00
2008-11-19 18:30:16 +00:00
// TODO: Parameter check logic required.
UUID soundId = UUID . Zero ;
if ( ! UUID . TryParse ( impact_sound , out soundId ) )
{
2012-07-04 20:15:00 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( impact_sound ) ;
if ( item ! = null & & item . Type = = ( int ) AssetType . Sound )
soundId = item . AssetID ;
2008-11-19 18:30:16 +00:00
}
2012-07-04 20:15:00 +00:00
2008-11-19 18:30:16 +00:00
m_host . CollisionSound = soundId ;
m_host . CollisionSoundVolume = ( float ) impact_volume ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetAnimation ( string id )
{
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
// This should only return a value if the avatar is in the same region
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
2008-11-05 14:02:36 +00:00
UUID avatar = ( UUID ) id ;
ScenePresence presence = World . GetScenePresence ( avatar ) ;
2008-11-10 05:42:02 +00:00
if ( presence = = null )
return "" ;
2008-11-05 14:02:36 +00:00
if ( m_host . RegionHandle = = presence . RegionHandle )
{
2012-03-22 00:10:41 +00:00
Dictionary < UUID , string > animationstateNames = DefaultAvatarAnimations . AnimStateNames ;
2008-11-05 14:02:36 +00:00
if ( presence ! = null )
{
2009-11-17 15:05:40 +00:00
AnimationSet currentAnims = presence . Animator . Animations ;
2008-11-05 15:26:10 +00:00
string currentAnimationState = String . Empty ;
if ( animationstateNames . TryGetValue ( currentAnims . DefaultAnimation . AnimID , out currentAnimationState ) )
return currentAnimationState ;
2008-11-05 14:02:36 +00:00
}
}
2010-09-24 14:26:53 +00:00
2008-09-26 02:51:00 +00:00
return String . Empty ;
}
2008-10-09 18:59:01 +00:00
public void llMessageLinked ( int linknumber , int num , string msg , string id )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-09 18:59:01 +00:00
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
2008-09-26 02:51:00 +00:00
2008-10-09 18:59:01 +00:00
UUID partItemID ;
foreach ( SceneObjectPart part in parts )
2009-02-14 21:25:22 +00:00
{
2012-07-04 20:22:43 +00:00
foreach ( TaskInventoryItem item in part . Inventory . GetInventoryItems ( ) )
2008-10-09 18:59:01 +00:00
{
if ( item . Type = = ScriptBaseClass . INVENTORY_SCRIPT )
2008-09-26 02:51:00 +00:00
{
2008-10-09 18:59:01 +00:00
partItemID = item . ItemID ;
2008-12-22 14:41:18 +00:00
int linkNumber = m_host . LinkNum ;
2010-08-25 23:08:53 +00:00
if ( m_host . ParentGroup . PrimCount = = 1 )
2008-12-22 13:03:30 +00:00
linkNumber = 0 ;
2008-10-09 18:59:01 +00:00
object [ ] resobj = new object [ ]
{
2008-12-22 13:03:30 +00:00
new LSL_Integer ( linkNumber ) , new LSL_Integer ( num ) , new LSL_String ( msg ) , new LSL_String ( id )
2008-10-09 18:59:01 +00:00
} ;
2008-09-26 02:51:00 +00:00
2008-10-09 18:59:01 +00:00
m_ScriptEngine . PostScriptEvent ( partItemID ,
new EventParams ( "link_message" ,
resobj , new DetectParams [ 0 ] ) ) ;
2008-09-26 02:51:00 +00:00
}
2008-10-09 18:59:01 +00:00
}
2009-02-14 21:25:22 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llPushObject ( string target , LSL_Vector impulse , LSL_Vector ang_impulse , int local )
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-17 23:19:00 +00:00
bool pushrestricted = World . RegionInfo . RegionSettings . RestrictPushing ;
bool pushAllowed = false ;
bool pusheeIsAvatar = false ;
UUID targetID = UUID . Zero ;
2009-07-28 09:40:07 +00:00
2008-10-17 23:19:00 +00:00
if ( ! UUID . TryParse ( target , out targetID ) )
2008-09-26 02:51:00 +00:00
return ;
2008-10-17 23:19:00 +00:00
ScenePresence pusheeav = null ;
Vector3 PusheePos = Vector3 . Zero ;
SceneObjectPart pusheeob = null ;
2008-10-20 01:42:02 +00:00
ScenePresence avatar = World . GetScenePresence ( targetID ) ;
if ( avatar ! = null )
2008-10-17 23:19:00 +00:00
{
2008-10-20 01:42:02 +00:00
pusheeIsAvatar = true ;
2008-10-17 23:19:00 +00:00
2008-10-20 01:42:02 +00:00
// Pushee doesn't have a physics actor
if ( avatar . PhysicsActor = = null )
return ;
2008-10-17 23:19:00 +00:00
2008-10-20 01:42:02 +00:00
// Pushee is in GodMode this pushing object isn't owned by them
if ( avatar . GodLevel > 0 & & m_host . OwnerID ! = targetID )
return ;
pusheeav = avatar ;
// Find pushee position
// Pushee Linked?
2012-03-09 02:38:11 +00:00
SceneObjectPart sitPart = pusheeav . ParentPart ;
if ( sitPart ! = null )
PusheePos = sitPart . AbsolutePosition ;
2008-10-20 01:42:02 +00:00
else
PusheePos = pusheeav . AbsolutePosition ;
2008-10-17 23:19:00 +00:00
}
if ( ! pusheeIsAvatar )
{
2008-10-20 01:42:02 +00:00
// not an avatar so push is not affected by parcel flags
2008-10-17 23:19:00 +00:00
pusheeob = World . GetSceneObjectPart ( ( UUID ) target ) ;
2008-10-20 01:42:02 +00:00
2008-10-17 23:19:00 +00:00
// We can't find object
if ( pusheeob = = null )
return ;
// Object not pushable. Not an attachment and has no physics component
2011-08-26 23:15:21 +00:00
if ( ! pusheeob . ParentGroup . IsAttachment & & pusheeob . PhysActor = = null )
2008-10-17 23:19:00 +00:00
return ;
PusheePos = pusheeob . AbsolutePosition ;
2008-10-20 01:42:02 +00:00
pushAllowed = true ;
2008-10-17 23:19:00 +00:00
}
else
{
2008-10-20 01:42:02 +00:00
if ( pushrestricted )
2008-10-17 23:19:00 +00:00
{
2008-10-20 01:42:02 +00:00
ILandObject targetlandObj = World . LandChannel . GetLandObject ( PusheePos . X , PusheePos . Y ) ;
// We didn't find the parcel but region is push restricted so assume it is NOT ok
if ( targetlandObj = = null )
return ;
// Need provisions for Group Owned here
2010-09-24 14:26:53 +00:00
if ( m_host . OwnerID = = targetlandObj . LandData . OwnerID | |
2009-10-02 09:10:52 +00:00
targetlandObj . LandData . IsGroupOwned | | m_host . OwnerID = = targetID )
2008-10-20 01:42:02 +00:00
{
pushAllowed = true ;
}
2008-10-17 23:19:00 +00:00
}
else
{
2008-10-20 01:42:02 +00:00
ILandObject targetlandObj = World . LandChannel . GetLandObject ( PusheePos . X , PusheePos . Y ) ;
if ( targetlandObj = = null )
2008-10-17 23:19:00 +00:00
{
2008-10-20 01:42:02 +00:00
// We didn't find the parcel but region isn't push restricted so assume it's ok
pushAllowed = true ;
2008-10-17 23:19:00 +00:00
}
else
{
2008-10-20 01:42:02 +00:00
// Parcel push restriction
2009-10-02 09:10:52 +00:00
if ( ( targetlandObj . LandData . Flags & ( uint ) ParcelFlags . RestrictPushObject ) = = ( uint ) ParcelFlags . RestrictPushObject )
2008-10-20 01:42:02 +00:00
{
// Need provisions for Group Owned here
2010-09-24 14:26:53 +00:00
if ( m_host . OwnerID = = targetlandObj . LandData . OwnerID | |
targetlandObj . LandData . IsGroupOwned | |
2009-10-02 09:10:52 +00:00
m_host . OwnerID = = targetID )
2008-10-20 01:42:02 +00:00
{
pushAllowed = true ;
}
2009-07-25 15:49:10 +00:00
//ParcelFlags.RestrictPushObject
2008-10-20 01:42:02 +00:00
//pushAllowed = true;
}
else
{
// Parcel isn't push restricted
pushAllowed = true ;
}
2008-10-17 23:19:00 +00:00
}
}
}
if ( pushAllowed )
{
float distance = ( PusheePos - m_host . AbsolutePosition ) . Length ( ) ;
float distance_term = distance * distance * distance ; // Script Energy
float pusher_mass = m_host . GetMass ( ) ;
float PUSH_ATTENUATION_DISTANCE = 17f ;
float PUSH_ATTENUATION_SCALE = 5f ;
float distance_attenuation = 1f ;
if ( distance > PUSH_ATTENUATION_DISTANCE )
{
float normalized_units = 1f + ( distance - PUSH_ATTENUATION_DISTANCE ) / PUSH_ATTENUATION_SCALE ;
distance_attenuation = 1f / normalized_units ;
}
2012-08-18 00:17:01 +00:00
Vector3 applied_linear_impulse = impulse ;
2008-10-17 23:19:00 +00:00
{
float impulse_length = applied_linear_impulse . Length ( ) ;
float desired_energy = impulse_length * pusher_mass ;
if ( desired_energy > 0f )
desired_energy + = distance_term ;
float scaling_factor = 1f ;
scaling_factor * = distance_attenuation ;
applied_linear_impulse * = scaling_factor ;
}
if ( pusheeIsAvatar )
{
if ( pusheeav ! = null )
{
if ( pusheeav . PhysicsActor ! = null )
{
if ( local ! = 0 )
{
applied_linear_impulse * = m_host . GetWorldRotation ( ) ;
}
2009-10-26 06:16:12 +00:00
pusheeav . PhysicsActor . AddForce ( applied_linear_impulse , true ) ;
2008-10-17 23:19:00 +00:00
}
}
}
else
{
if ( pusheeob ! = null )
{
if ( pusheeob . PhysActor ! = null )
{
pusheeob . ApplyImpulse ( applied_linear_impulse , local ! = 0 ) ;
}
}
}
}
2008-09-26 02:51:00 +00:00
}
public void llPassCollisions ( int pass )
{
m_host . AddScriptLPS ( 1 ) ;
2010-01-03 21:10:45 +00:00
if ( pass = = 0 )
2009-12-31 17:41:07 +00:00
{
2012-05-15 00:02:38 +00:00
m_host . PassCollisions = false ;
2009-12-31 17:41:07 +00:00
}
else
{
2012-05-15 00:02:38 +00:00
m_host . PassCollisions = true ;
2009-12-31 17:41:07 +00:00
}
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetScriptName ( )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
return m_item . Name ! = null ? m_item . Name : String . Empty ;
2008-09-26 02:51:00 +00:00
}
2011-05-20 19:19:32 +00:00
public LSL_Integer llGetLinkNumberOfSides ( int link )
2011-05-19 05:34:11 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2011-05-20 19:19:32 +00:00
SceneObjectPart linkedPart ;
if ( link = = ScriptBaseClass . LINK_ROOT )
linkedPart = m_host . ParentGroup . RootPart ;
else if ( link = = ScriptBaseClass . LINK_THIS )
linkedPart = m_host ;
else
linkedPart = m_host . ParentGroup . GetLinkNumPart ( link ) ;
return GetNumberOfSides ( linkedPart ) ;
2011-05-19 05:34:11 +00:00
}
2008-09-26 02:51:00 +00:00
public LSL_Integer llGetNumberOfSides ( )
{
m_host . AddScriptLPS ( 1 ) ;
return GetNumberOfSides ( m_host ) ;
}
2009-07-06 13:09:03 +00:00
protected int GetNumberOfSides ( SceneObjectPart part )
2008-09-26 02:51:00 +00:00
{
2010-02-01 22:29:21 +00:00
int sides = part . GetNumberOfSides ( ) ;
2008-09-26 02:51:00 +00:00
2010-02-01 22:33:15 +00:00
if ( part . GetPrimType ( ) = = PrimType . SPHERE & & part . Shape . ProfileHollow > 0 )
2008-09-26 02:51:00 +00:00
{
2010-02-01 22:29:21 +00:00
// Make up for a bug where LSL shows 4 sides rather than 2
sides + = 2 ;
2008-09-26 02:51:00 +00:00
}
2010-02-01 22:29:21 +00:00
return sides ;
}
2010-09-24 14:26:53 +00:00
2008-09-26 02:51:00 +00:00
/ * The new / changed functions were tested with the following LSL script :
default
{
state_entry ( )
{
rotation rot = llEuler2Rot ( < 0 , 70 , 0 > * DEG_TO_RAD ) ;
llOwnerSay ( "to get here, we rotate over: " + ( string ) llRot2Axis ( rot ) ) ;
llOwnerSay ( "and we rotate for: " + ( llRot2Angle ( rot ) * RAD_TO_DEG ) ) ;
// convert back and forth between quaternion <-> vector and angle
rotation newrot = llAxisAngle2Rot ( llRot2Axis ( rot ) , llRot2Angle ( rot ) ) ;
llOwnerSay ( "Old rotation was: " + ( string ) rot ) ;
llOwnerSay ( "re-converted rotation is: " + ( string ) newrot ) ;
llSetRot ( rot ) ; // to check the parameters in the prim
}
}
* /
// Xantor 29/apr/2008
// Returns rotation described by rotating angle radians about axis.
// q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
public LSL_Rotation llAxisAngle2Rot ( LSL_Vector axis , double angle )
{
m_host . AddScriptLPS ( 1 ) ;
double x , y , z , s , t ;
2009-12-16 03:12:24 +00:00
s = Math . Cos ( angle * 0.5 ) ;
t = Math . Sin ( angle * 0.5 ) ; // temp value to avoid 2 more sin() calcs
2008-09-26 02:51:00 +00:00
x = axis . x * t ;
y = axis . y * t ;
z = axis . z * t ;
return new LSL_Rotation ( x , y , z , s ) ;
}
// Xantor 29/apr/2008
// converts a Quaternion to X,Y,Z axis rotations
public LSL_Vector llRot2Axis ( LSL_Rotation rot )
{
m_host . AddScriptLPS ( 1 ) ;
double x , y , z ;
if ( rot . s > 1 ) // normalization needed
{
double length = Math . Sqrt ( rot . x * rot . x + rot . y * rot . y +
rot . z * rot . z + rot . s * rot . s ) ;
rot . x / = length ;
rot . y / = length ;
rot . z / = length ;
rot . s / = length ;
}
// double angle = 2 * Math.Acos(rot.s);
double s = Math . Sqrt ( 1 - rot . s * rot . s ) ;
if ( s < 0.001 )
{
x = 1 ;
y = z = 0 ;
}
else
{
x = rot . x / s ; // normalise axis
y = rot . y / s ;
z = rot . z / s ;
}
return new LSL_Vector ( x , y , z ) ;
}
// Returns the angle of a quaternion (see llRot2Axis for the axis)
public LSL_Float llRot2Angle ( LSL_Rotation rot )
{
m_host . AddScriptLPS ( 1 ) ;
if ( rot . s > 1 ) // normalization needed
{
double length = Math . Sqrt ( rot . x * rot . x + rot . y * rot . y +
rot . z * rot . z + rot . s * rot . s ) ;
rot . x / = length ;
rot . y / = length ;
rot . z / = length ;
rot . s / = length ;
}
double angle = 2 * Math . Acos ( rot . s ) ;
return angle ;
}
public LSL_Float llAcos ( double val )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Acos ( val ) ;
}
public LSL_Float llAsin ( double val )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Asin ( val ) ;
}
2012-01-05 13:37:08 +00:00
// jcochran 5/jan/2012
2008-09-26 02:51:00 +00:00
public LSL_Float llAngleBetween ( LSL_Rotation a , LSL_Rotation b )
{
m_host . AddScriptLPS ( 1 ) ;
2012-01-05 13:37:08 +00:00
double aa = ( a . x * a . x + a . y * a . y + a . z * a . z + a . s * a . s ) ;
double bb = ( b . x * b . x + b . y * b . y + b . z * b . z + b . s * b . s ) ;
double aa_bb = aa * bb ;
if ( aa_bb = = 0 ) return 0.0 ;
double ab = ( a . x * b . x + a . y * b . y + a . z * b . z + a . s * b . s ) ;
double quotient = ( ab * ab ) / aa_bb ;
if ( quotient > = 1.0 ) return 0.0 ;
return Math . Acos ( 2 * quotient - 1 ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetInventoryKey ( string name )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
2012-07-04 20:25:58 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( name ) ;
if ( item = = null )
return UUID . Zero . ToString ( ) ;
if ( ( item . CurrentPermissions
& ( uint ) ( PermissionMask . Copy | PermissionMask . Transfer | PermissionMask . Modify ) )
= = ( uint ) ( PermissionMask . Copy | PermissionMask . Transfer | PermissionMask . Modify ) )
2008-09-26 02:51:00 +00:00
{
2012-07-04 20:25:58 +00:00
return item . AssetID . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
return UUID . Zero . ToString ( ) ;
}
public void llAllowInventoryDrop ( int add )
{
m_host . AddScriptLPS ( 1 ) ;
if ( add ! = 0 )
m_host . ParentGroup . RootPart . AllowedDrop = true ;
else
m_host . ParentGroup . RootPart . AllowedDrop = false ;
2008-11-14 17:24:56 +00:00
2008-11-15 02:21:52 +00:00
// Update the object flags
m_host . ParentGroup . RootPart . aggregateScriptEvents ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGetSunDirection ( )
{
m_host . AddScriptLPS ( 1 ) ;
LSL_Vector SunDoubleVector3 ;
Vector3 SunFloatVector3 ;
2009-02-10 13:10:57 +00:00
// sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule
2008-09-26 02:51:00 +00:00
// have to convert from Vector3 (float) to LSL_Vector (double)
SunFloatVector3 = World . RegionInfo . RegionSettings . SunVector ;
SunDoubleVector3 . x = ( double ) SunFloatVector3 . X ;
SunDoubleVector3 . y = ( double ) SunFloatVector3 . Y ;
SunDoubleVector3 . z = ( double ) SunFloatVector3 . Z ;
return SunDoubleVector3 ;
}
public LSL_Vector llGetTextureOffset ( int face )
{
m_host . AddScriptLPS ( 1 ) ;
return GetTextureOffset ( m_host , face ) ;
}
2009-07-06 13:09:03 +00:00
protected LSL_Vector GetTextureOffset ( SceneObjectPart part , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
LSL_Vector offset = new LSL_Vector ( ) ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
face = 0 ;
}
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
offset . x = tex . GetFace ( ( uint ) face ) . OffsetU ;
offset . y = tex . GetFace ( ( uint ) face ) . OffsetV ;
offset . z = 0.0 ;
return offset ;
}
else
{
return offset ;
}
}
public LSL_Vector llGetTextureScale ( int side )
{
m_host . AddScriptLPS ( 1 ) ;
Primitive . TextureEntry tex = m_host . Shape . Textures ;
LSL_Vector scale ;
if ( side = = - 1 )
{
side = 0 ;
}
scale . x = tex . GetFace ( ( uint ) side ) . RepeatU ;
scale . y = tex . GetFace ( ( uint ) side ) . RepeatV ;
scale . z = 0.0 ;
return scale ;
}
public LSL_Float llGetTextureRot ( int face )
{
m_host . AddScriptLPS ( 1 ) ;
return GetTextureRot ( m_host , face ) ;
}
2009-07-06 13:09:03 +00:00
protected LSL_Float GetTextureRot ( SceneObjectPart part , int face )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntry tex = part . Shape . Textures ;
if ( face = = - 1 )
{
face = 0 ;
}
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
return tex . GetFace ( ( uint ) face ) . Rotation ;
}
else
{
return 0.0 ;
}
}
public LSL_Integer llSubStringIndex ( string source , string pattern )
{
m_host . AddScriptLPS ( 1 ) ;
return source . IndexOf ( pattern ) ;
}
public LSL_String llGetOwnerKey ( string id )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key = new UUID ( ) ;
if ( UUID . TryParse ( id , out key ) )
{
try
{
2009-03-24 22:12:48 +00:00
SceneObjectPart obj = World . GetSceneObjectPart ( key ) ;
2008-09-26 02:51:00 +00:00
if ( obj = = null )
return id ; // the key is for an agent so just return the key
else
return obj . OwnerID . ToString ( ) ;
}
catch ( KeyNotFoundException )
{
return id ; // The Object/Agent not in the region so just return the key
}
}
else
{
return UUID . Zero . ToString ( ) ;
}
}
public LSL_Vector llGetCenterOfMass ( )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-14 21:41:57 +00:00
Vector3 center = m_host . GetGeometricCenter ( ) ;
return new LSL_Vector ( center . X , center . Y , center . Z ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_List llListSort ( LSL_List src , int stride , int ascending )
{
m_host . AddScriptLPS ( 1 ) ;
if ( stride < = 0 )
{
stride = 1 ;
}
return src . Sort ( stride , ascending ) ;
}
public LSL_Integer llGetListLength ( LSL_List src )
{
m_host . AddScriptLPS ( 1 ) ;
if ( src = = null )
{
return 0 ;
}
else
{
return src . Length ;
}
}
public LSL_Integer llList2Integer ( LSL_List src , int index )
{
m_host . AddScriptLPS ( 1 ) ;
if ( index < 0 )
{
index = src . Length + index ;
}
2009-10-19 11:03:14 +00:00
if ( index > = src . Length | | index < 0 )
2008-09-26 02:51:00 +00:00
{
return 0 ;
}
2012-08-13 11:20:19 +00:00
// 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 )
{
return 0 ;
}
2008-09-26 02:51:00 +00:00
try
{
2012-08-13 11:20:19 +00:00
2008-09-26 02:51:00 +00:00
if ( src . Data [ index ] is LSL_Integer )
2012-08-13 11:20:19 +00:00
return ( LSL_Integer ) src . Data [ index ] ;
2008-09-26 02:51:00 +00:00
else if ( src . Data [ index ] is LSL_Float )
2012-08-13 11:20:19 +00:00
return Convert . ToInt32 ( ( ( LSL_Float ) src . Data [ index ] ) . value ) ;
2008-11-11 01:02:48 +00:00
return new LSL_Integer ( src . Data [ index ] . ToString ( ) ) ;
2008-09-26 02:51:00 +00:00
}
catch ( FormatException )
{
return 0 ;
}
}
public LSL_Float llList2Float ( LSL_List src , int index )
{
m_host . AddScriptLPS ( 1 ) ;
if ( index < 0 )
{
index = src . Length + index ;
}
2009-10-19 11:03:14 +00:00
if ( index > = src . Length | | index < 0 )
2008-09-26 02:51:00 +00:00
{
return 0.0 ;
}
2012-08-13 11:20:19 +00:00
// Vectors & Rotations always return zero in SL
else if ( src . Data [ index ] is LSL_Vector | |
src . Data [ index ] is LSL_Rotation )
{
return 0 ;
}
// valid keys seem to get parsed as integers then converted to floats
else
{
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 ) ;
}
}
2008-09-26 02:51:00 +00:00
try
{
if ( src . Data [ index ] is LSL_Integer )
2012-08-13 11:20:19 +00:00
return Convert . ToDouble ( ( ( LSL_Integer ) src . Data [ index ] ) . value ) ;
2008-09-26 02:51:00 +00:00
else if ( src . Data [ index ] is LSL_Float )
2012-08-13 11:20:19 +00:00
return Convert . ToDouble ( ( ( LSL_Float ) src . Data [ index ] ) . value ) ;
2008-09-26 02:51:00 +00:00
else if ( src . Data [ index ] is LSL_String )
2012-08-13 11:20:19 +00:00
return Convert . ToDouble ( ( ( LSL_String ) src . Data [ index ] ) . m_string ) ;
2008-09-26 02:51:00 +00:00
return Convert . ToDouble ( src . Data [ index ] ) ;
}
catch ( FormatException )
{
return 0.0 ;
}
}
public LSL_String llList2String ( LSL_List src , int index )
{
m_host . AddScriptLPS ( 1 ) ;
if ( index < 0 )
{
index = src . Length + index ;
}
2009-10-19 11:03:14 +00:00
if ( index > = src . Length | | index < 0 )
2008-09-26 02:51:00 +00:00
{
return String . Empty ;
}
return src . Data [ index ] . ToString ( ) ;
}
2012-08-13 11:20:19 +00:00
public LSL_Key llList2Key ( LSL_List src , int index )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
if ( index < 0 )
{
index = src . Length + index ;
}
2012-08-13 11:20:19 +00:00
2009-10-19 11:03:14 +00:00
if ( index > = src . Length | | index < 0 )
2008-09-26 02:51:00 +00:00
{
return "" ;
}
2012-08-13 11:20:19 +00:00
// SL spits out an empty string for types other than key & string
// At the time of patching, LSL_Key is currently LSL_String,
// so the OR check may be a little redundant, but it's being done
// for completion and should LSL_Key ever be implemented
// as it's own struct
else if ( ! ( src . Data [ index ] is LSL_String | |
src . Data [ index ] is LSL_Key ) )
{
return "" ;
}
2008-09-26 02:51:00 +00:00
return src . Data [ index ] . ToString ( ) ;
}
public LSL_Vector llList2Vector ( LSL_List src , int index )
{
m_host . AddScriptLPS ( 1 ) ;
if ( index < 0 )
{
index = src . Length + index ;
}
2009-10-19 11:03:14 +00:00
if ( index > = src . Length | | index < 0 )
2008-09-26 02:51:00 +00:00
{
return new LSL_Vector ( 0 , 0 , 0 ) ;
}
if ( src . Data [ index ] . GetType ( ) = = typeof ( LSL_Vector ) )
{
return ( LSL_Vector ) src . Data [ index ] ;
}
2012-08-13 11:20:19 +00:00
// SL spits always out ZERO_VECTOR for anything other than
// strings or vectors. Although keys always return ZERO_VECTOR,
// it is currently difficult to make the distinction between
// 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 ) ;
}
2008-09-26 02:51:00 +00:00
else
{
return new LSL_Vector ( src . Data [ index ] . ToString ( ) ) ;
}
}
public LSL_Rotation llList2Rot ( LSL_List src , int index )
{
m_host . AddScriptLPS ( 1 ) ;
if ( index < 0 )
{
index = src . Length + index ;
}
2009-10-19 11:03:14 +00:00
if ( index > = src . Length | | index < 0 )
2008-09-26 02:51:00 +00:00
{
return new LSL_Rotation ( 0 , 0 , 0 , 1 ) ;
}
2012-08-13 11:20:19 +00:00
// SL spits always out ZERO_ROTATION for anything other than
// strings or vectors. Although keys always return ZERO_ROTATION,
// it is currently difficult to make the distinction between
// 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 ) )
2008-09-26 02:51:00 +00:00
{
return ( LSL_Rotation ) src . Data [ index ] ;
}
else
{
return new LSL_Rotation ( src . Data [ index ] . ToString ( ) ) ;
}
}
public LSL_List llList2List ( LSL_List src , int start , int end )
{
m_host . AddScriptLPS ( 1 ) ;
return src . GetSublist ( start , end ) ;
}
public LSL_List llDeleteSubList ( LSL_List src , int start , int end )
{
2008-10-17 19:01:01 +00:00
return src . DeleteSublist ( start , end ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llGetListEntryType ( LSL_List src , int index )
{
m_host . AddScriptLPS ( 1 ) ;
if ( index < 0 )
{
index = src . Length + index ;
}
if ( index > = src . Length )
{
return 0 ;
}
if ( src . Data [ index ] is LSL_Integer | | src . Data [ index ] is Int32 )
return 1 ;
if ( src . Data [ index ] is LSL_Float | | src . Data [ index ] is Single | | src . Data [ index ] is Double )
return 2 ;
if ( src . Data [ index ] is LSL_String | | src . Data [ index ] is String )
{
UUID tuuid ;
if ( UUID . TryParse ( src . Data [ index ] . ToString ( ) , out tuuid ) )
{
return 4 ;
}
else
{
return 3 ;
}
}
if ( src . Data [ index ] is LSL_Vector )
return 5 ;
if ( src . Data [ index ] is LSL_Rotation )
return 6 ;
if ( src . Data [ index ] is LSL_List )
return 7 ;
return 0 ;
}
/// <summary>
/// Process the supplied list and return the
/// content of the list formatted as a comma
/// separated list. There is a space after
/// each comma.
/// </summary>
public LSL_String llList2CSV ( LSL_List src )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-24 12:53:53 +00:00
return string . Join ( ", " ,
( new List < object > ( src . Data ) ) . ConvertAll < string > ( o = >
{
return o . ToString ( ) ;
} ) . ToArray ( ) ) ;
2008-09-26 02:51:00 +00:00
}
/// <summary>
/// The supplied string is scanned for commas
/// and converted into a list. Commas are only
/// effective if they are encountered outside
/// of '<' '>' delimiters. Any whitespace
/// before or after an element is trimmed.
/// </summary>
public LSL_List llCSV2List ( string src )
{
LSL_List result = new LSL_List ( ) ;
int parens = 0 ;
int start = 0 ;
int length = 0 ;
m_host . AddScriptLPS ( 1 ) ;
for ( int i = 0 ; i < src . Length ; i + + )
{
switch ( src [ i ] )
{
case '<' :
parens + + ;
length + + ;
break ;
case '>' :
if ( parens > 0 )
parens - - ;
length + + ;
break ;
case ',' :
if ( parens = = 0 )
{
2010-07-02 02:26:55 +00:00
result . Add ( new LSL_String ( src . Substring ( start , length ) . Trim ( ) ) ) ;
2008-09-26 02:51:00 +00:00
start + = length + 1 ;
length = 0 ;
}
else
{
length + + ;
}
break ;
default :
length + + ;
break ;
}
}
2011-07-04 13:45:21 +00:00
result . Add ( new LSL_String ( src . Substring ( start , length ) . Trim ( ) ) ) ;
2008-09-26 02:51:00 +00:00
return result ;
}
/// <summary>
/// Randomizes the list, be arbitrarily reordering
/// sublists of stride elements. As the stride approaches
/// the size of the list, the options become very
/// limited.
/// </summary>
/// <remarks>
/// This could take a while for very large list
/// sizes.
/// </remarks>
public LSL_List llListRandomize ( LSL_List src , int stride )
{
LSL_List result ;
Random rand = new Random ( ) ;
int chunkk ;
int [ ] chunks ;
m_host . AddScriptLPS ( 1 ) ;
if ( stride < = 0 )
{
stride = 1 ;
}
// Stride MUST be a factor of the list length
// If not, then return the src list. This also
// traps those cases where stride > length.
if ( src . Length ! = stride & & src . Length % stride = = 0 )
{
chunkk = src . Length / stride ;
chunks = new int [ chunkk ] ;
for ( int i = 0 ; i < chunkk ; i + + )
chunks [ i ] = i ;
// Knuth shuffle the chunkk index
for ( int i = chunkk - 1 ; i > = 1 ; i - - )
{
// Elect an unrandomized chunk to swap
int index = rand . Next ( i + 1 ) ;
int tmp ;
// and swap position with first unrandomized chunk
tmp = chunks [ i ] ;
chunks [ i ] = chunks [ index ] ;
chunks [ index ] = tmp ;
}
// Construct the randomized list
result = new LSL_List ( ) ;
for ( int i = 0 ; i < chunkk ; i + + )
{
for ( int j = 0 ; j < stride ; j + + )
{
result . Add ( src . Data [ chunks [ i ] * stride + j ] ) ;
}
}
}
else {
object [ ] array = new object [ src . Length ] ;
Array . Copy ( src . Data , 0 , array , 0 , src . Length ) ;
result = new LSL_List ( array ) ;
}
return result ;
}
/// <summary>
/// Elements in the source list starting with 0 and then
/// every i+stride. If the stride is negative then the scan
/// is backwards producing an inverted result.
/// Only those elements that are also in the specified
/// range are included in the result.
/// </summary>
public LSL_List llList2ListStrided ( LSL_List src , int start , int end , int stride )
{
LSL_List result = new LSL_List ( ) ;
int [ ] si = new int [ 2 ] ;
int [ ] ei = new int [ 2 ] ;
bool twopass = false ;
m_host . AddScriptLPS ( 1 ) ;
// First step is always to deal with negative indices
if ( start < 0 )
start = src . Length + start ;
if ( end < 0 )
end = src . Length + end ;
// Out of bounds indices are OK, just trim them
// accordingly
if ( start > src . Length )
start = src . Length ;
if ( end > src . Length )
end = src . Length ;
2009-09-29 11:10:54 +00:00
if ( stride = = 0 )
stride = 1 ;
2008-09-26 02:51:00 +00:00
// There may be one or two ranges to be considered
if ( start ! = end )
{
if ( start < = end )
{
si [ 0 ] = start ;
ei [ 0 ] = end ;
}
else
{
si [ 1 ] = start ;
ei [ 1 ] = src . Length ;
si [ 0 ] = 0 ;
ei [ 0 ] = end ;
twopass = true ;
}
// The scan always starts from the beginning of the
// source list, but members are only selected if they
// fall within the specified sub-range. The specified
// range values are inclusive.
// A negative stride reverses the direction of the
// scan producing an inverted list as a result.
if ( stride > 0 )
{
for ( int i = 0 ; i < src . Length ; i + = stride )
{
if ( i < = ei [ 0 ] & & i > = si [ 0 ] )
result . Add ( src . Data [ i ] ) ;
if ( twopass & & i > = si [ 1 ] & & i < = ei [ 1 ] )
result . Add ( src . Data [ i ] ) ;
}
}
else if ( stride < 0 )
{
for ( int i = src . Length - 1 ; i > = 0 ; i + = stride )
{
if ( i < = ei [ 0 ] & & i > = si [ 0 ] )
result . Add ( src . Data [ i ] ) ;
if ( twopass & & i > = si [ 1 ] & & i < = ei [ 1 ] )
result . Add ( src . Data [ i ] ) ;
}
}
}
2009-09-16 13:44:48 +00:00
else
{
2009-09-29 11:10:54 +00:00
if ( start % stride = = 0 )
{
result . Add ( src . Data [ start ] ) ;
}
2009-09-16 13:44:48 +00:00
}
2008-09-26 02:51:00 +00:00
return result ;
}
public LSL_Integer llGetRegionAgentCount ( )
{
m_host . AddScriptLPS ( 1 ) ;
2010-03-19 12:51:16 +00:00
return new LSL_Integer ( World . GetRootAgentCount ( ) ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGetRegionCorner ( )
{
m_host . AddScriptLPS ( 1 ) ;
return new LSL_Vector ( World . RegionInfo . RegionLocX * Constants . RegionSize , World . RegionInfo . RegionLocY * Constants . RegionSize , 0 ) ;
}
/// <summary>
/// Insert the list identified by <src> into the
/// list designated by <dest> such that the first
/// new element has the index specified by <index>
/// </summary>
public LSL_List llListInsertList ( LSL_List dest , LSL_List src , int index )
{
LSL_List pref = null ;
LSL_List suff = null ;
m_host . AddScriptLPS ( 1 ) ;
if ( index < 0 )
{
index = index + dest . Length ;
if ( index < 0 )
{
index = 0 ;
}
}
if ( index ! = 0 )
{
pref = dest . GetSublist ( 0 , index - 1 ) ;
if ( index < dest . Length )
{
suff = dest . GetSublist ( index , - 1 ) ;
return pref + src + suff ;
}
else
{
return pref + src ;
}
}
else
{
if ( index < dest . Length )
{
suff = dest . GetSublist ( index , - 1 ) ;
return src + suff ;
}
else
{
return src ;
}
}
}
/// <summary>
/// Returns the index of the first occurrence of test
/// in src.
/// </summary>
public LSL_Integer llListFindList ( LSL_List src , LSL_List test )
{
int index = - 1 ;
int length = src . Length - test . Length + 1 ;
m_host . AddScriptLPS ( 1 ) ;
// If either list is empty, do not match
if ( src . Length ! = 0 & & test . Length ! = 0 )
{
for ( int i = 0 ; i < length ; i + + )
{
2008-11-08 15:31:02 +00:00
if ( src . Data [ i ] . Equals ( test . Data [ 0 ] ) )
{
int j ;
for ( j = 1 ; j < test . Length ; j + + )
if ( ! src . Data [ i + j ] . Equals ( test . Data [ j ] ) )
break ;
if ( j = = test . Length )
{
index = i ;
break ;
}
}
2008-09-26 02:51:00 +00:00
}
}
return index ;
}
public LSL_String llGetObjectName ( )
{
m_host . AddScriptLPS ( 1 ) ;
return m_host . Name ! = null ? m_host . Name : String . Empty ;
}
public void llSetObjectName ( string name )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . Name = name ! = null ? name : String . Empty ;
}
public LSL_String llGetDate ( )
{
m_host . AddScriptLPS ( 1 ) ;
DateTime date = DateTime . Now . ToUniversalTime ( ) ;
string result = date . ToString ( "yyyy-MM-dd" ) ;
return result ;
}
public LSL_Integer llEdgeOfWorld ( LSL_Vector pos , LSL_Vector dir )
{
m_host . AddScriptLPS ( 1 ) ;
2009-03-29 23:59:14 +00:00
// 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 ) ;
2009-07-28 09:40:07 +00:00
2009-03-29 23:59:14 +00:00
if ( dir . x = = 0 )
{
2009-03-31 02:00:33 +00:00
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 ) ;
}
2009-03-29 23:59:14 +00:00
}
else
{
LSL_Float mag ;
2009-03-31 02:00:33 +00:00
if ( dir . x > 0 )
{
2009-07-28 09:40:07 +00:00
mag = ( Constants . RegionSize - pos . x ) / dir . x ;
2009-03-31 02:00:33 +00:00
}
else
{
2009-03-29 23:59:14 +00:00
mag = ( pos . x / dir . x ) ;
2009-03-31 02:00:33 +00:00
}
2009-03-29 23:59:14 +00:00
mag = Math . Abs ( mag ) ;
edge . y = pos . y + ( dir . y * mag ) ;
if ( edge . y > Constants . RegionSize | | edge . y < 0 )
{
2009-03-31 02:00:33 +00:00
// Y goes out of bounds first
2009-03-29 23:59:14 +00:00
edge . y = dir . y / Math . Abs ( dir . y ) ;
}
else
{
// X goes out of bounds first or its a corner exit
edge . y = 0 ;
edge . x = dir . x / Math . Abs ( dir . x ) ;
}
}
2009-07-28 09:40:07 +00:00
2009-09-26 14:48:21 +00:00
List < GridRegion > neighbors = World . GridService . GetNeighbours ( World . RegionInfo . ScopeID , World . RegionInfo . RegionID ) ;
2009-07-28 09:40:07 +00:00
2009-03-31 02:00:33 +00:00
uint neighborX = World . RegionInfo . RegionLocX + ( uint ) dir . x ;
uint neighborY = World . RegionInfo . RegionLocY + ( uint ) dir . y ;
2009-07-28 09:40:07 +00:00
2009-09-26 14:48:21 +00:00
foreach ( GridRegion sri in neighbors )
2009-03-31 02:00:33 +00:00
{
2012-01-29 20:39:30 +00:00
if ( sri . RegionCoordX = = neighborX & & sri . RegionCoordY = = neighborY )
2009-03-31 02:00:33 +00:00
return 0 ;
}
2009-07-28 09:40:07 +00:00
2009-03-31 02:00:33 +00:00
return 1 ;
2008-09-26 02:51:00 +00:00
}
2008-10-22 23:07:45 +00:00
/// <summary>
/// Not fully implemented yet. Still to do:-
/// AGENT_BUSY
/// Remove as they are done
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Integer llGetAgentInfo ( string id )
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-15 04:55:13 +00:00
UUID key = new UUID ( ) ;
if ( ! UUID . TryParse ( id , out key ) )
{
return 0 ;
}
int flags = 0 ;
ScenePresence agent = World . GetScenePresence ( key ) ;
if ( agent = = null )
{
return 0 ;
}
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
if ( agent . IsChildAgent )
return 0 ; // Fail if they are not in the same region
2008-10-23 20:06:23 +00:00
// note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL
2008-10-15 04:55:13 +00:00
if ( agent . SetAlwaysRun )
{
flags | = ScriptBaseClass . AGENT_ALWAYS_RUN ;
}
2008-10-22 23:07:45 +00:00
if ( agent . HasAttachments ( ) )
{
flags | = ScriptBaseClass . AGENT_ATTACHMENTS ;
if ( agent . HasScriptedAttachments ( ) )
flags | = ScriptBaseClass . AGENT_SCRIPTED ;
}
2008-10-15 04:55:13 +00:00
if ( ( agent . AgentControlFlags & ( uint ) AgentManager . ControlFlags . AGENT_CONTROL_FLY ) ! = 0 )
{
flags | = ScriptBaseClass . AGENT_FLYING ;
2008-10-23 20:06:23 +00:00
flags | = ScriptBaseClass . AGENT_IN_AIR ; // flying always implies in-air, even if colliding with e.g. a wall
2008-10-15 04:55:13 +00:00
}
if ( ( agent . AgentControlFlags & ( uint ) AgentManager . ControlFlags . AGENT_CONTROL_AWAY ) ! = 0 )
{
flags | = ScriptBaseClass . AGENT_AWAY ;
}
2008-10-23 20:06:23 +00:00
// seems to get unset, even if in mouselook, when avatar is sitting on a prim???
2008-10-15 04:55:13 +00:00
if ( ( agent . AgentControlFlags & ( uint ) AgentManager . ControlFlags . AGENT_CONTROL_MOUSELOOK ) ! = 0 )
{
flags | = ScriptBaseClass . AGENT_MOUSELOOK ;
}
2009-03-27 22:13:09 +00:00
if ( ( agent . State & ( byte ) AgentState . Typing ) ! = ( byte ) 0 )
2008-10-15 04:55:13 +00:00
{
flags | = ScriptBaseClass . AGENT_TYPING ;
}
2011-12-03 00:33:24 +00:00
string agentMovementAnimation = agent . Animator . CurrentMovementAnimation ;
2008-10-23 20:06:23 +00:00
if ( agentMovementAnimation = = "CROUCH" )
{
flags | = ScriptBaseClass . AGENT_CROUCHING ;
}
2009-07-28 09:40:07 +00:00
if ( agentMovementAnimation = = "WALK" | | agentMovementAnimation = = "CROUCHWALK" )
2008-10-22 14:09:58 +00:00
{
flags | = ScriptBaseClass . AGENT_WALKING ;
}
2008-10-23 20:06:23 +00:00
// not colliding implies in air. Note: flying also implies in-air, even if colliding (see above)
// note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL.
// note: this may need some tweaking when walking downhill. you "fall down" for a brief instant
// and don't collide when walking downhill, which instantly registers as in-air, briefly. should
// there be some minimum non-collision threshold time before claiming the avatar is in-air?
2011-12-12 10:43:38 +00:00
if ( ( flags & ScriptBaseClass . AGENT_WALKING ) = = 0 & & ! agent . IsColliding )
2008-10-23 20:06:23 +00:00
{
flags | = ScriptBaseClass . AGENT_IN_AIR ;
}
2012-03-09 02:38:11 +00:00
if ( agent . ParentPart ! = null )
2008-10-23 20:06:23 +00:00
{
flags | = ScriptBaseClass . AGENT_ON_OBJECT ;
flags | = ScriptBaseClass . AGENT_SITTING ;
}
2010-09-24 14:26:53 +00:00
if ( agent . Animator . Animations . DefaultAnimation . AnimID
2012-03-22 00:10:41 +00:00
= = DefaultAvatarAnimations . AnimsUUID [ "SIT_GROUND_CONSTRAINED" ] )
2008-10-23 20:06:23 +00:00
{
flags | = ScriptBaseClass . AGENT_SITTING ;
}
2008-10-15 04:55:13 +00:00
return flags ;
2008-09-26 02:51:00 +00:00
}
2008-09-26 18:40:16 +00:00
public LSL_String llGetAgentLanguage ( string id )
{
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
// This should only return a value if the avatar is in the same region
2009-01-31 18:27:44 +00:00
//ckrinke 1-30-09 : This needs to parse the XMLRPC language field supplied
//by the client at login. Currently returning only en-us until our I18N
//effort gains momentum
2008-09-26 18:40:16 +00:00
m_host . AddScriptLPS ( 1 ) ;
2009-01-31 18:27:44 +00:00
return "en-us" ;
2008-09-26 18:40:16 +00:00
}
2012-05-08 14:52:25 +00:00
/// <summary>
/// http://wiki.secondlife.com/wiki/LlGetAgentList
/// The list of options is currently not used in SL
/// scope is one of:-
/// AGENT_LIST_REGION - all in the region
/// 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.
/// </summary>
public LSL_List llGetAgentList ( LSL_Integer scope , LSL_List options )
{
m_host . AddScriptLPS ( 1 ) ;
// 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 ;
bool parcelOwned = scope = = ScriptBaseClass . AGENT_LIST_PARCEL_OWNER ;
bool parcel = scope = = ScriptBaseClass . AGENT_LIST_PARCEL ;
LSL_List result = new LSL_List ( ) ;
if ( ! regionWide & & ! parcelOwned & & ! parcel )
{
result . Add ( "INVALID_SCOPE" ) ;
return result ;
}
ILandObject land ;
Vector3 pos ;
UUID id = UUID . Zero ;
if ( parcel | | parcelOwned )
{
pos = m_host . ParentGroup . RootPart . GetWorldPosition ( ) ;
land = World . LandChannel . GetLandObject ( pos . X , pos . Y ) ;
if ( land = = null )
{
id = UUID . Zero ;
}
else
{
if ( parcelOwned )
{
id = land . LandData . OwnerID ;
}
else
{
id = land . LandData . GlobalID ;
}
}
}
World . ForEachRootScenePresence (
delegate ( ScenePresence ssp )
{
// Gods are not listed in SL
if ( ! ssp . IsDeleted & & ssp . GodLevel = = 0.0 & & ! ssp . IsChildAgent )
{
if ( ! regionWide )
{
pos = ssp . AbsolutePosition ;
land = World . LandChannel . GetLandObject ( pos . X , pos . Y ) ;
if ( land ! = null )
{
if ( parcelOwned & & land . LandData . OwnerID = = id | |
parcel & & land . LandData . GlobalID = = id )
{
result . Add ( ssp . UUID . ToString ( ) ) ;
}
}
}
else
{
result . Add ( ssp . UUID . ToString ( ) ) ;
}
}
// Maximum of 100 results
if ( result . Length > 99 )
{
return ;
}
}
) ;
return result ;
}
2008-09-26 18:40:16 +00:00
2008-09-26 02:51:00 +00:00
public void llAdjustSoundVolume ( double volume )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . AdjustSoundGain ( volume ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetSoundRadius ( double radius )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . SoundRadius = radius ;
}
public LSL_String llKey2Name ( string id )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key = new UUID ( ) ;
if ( UUID . TryParse ( id , out key ) )
{
ScenePresence presence = World . GetScenePresence ( key ) ;
if ( presence ! = null )
{
return presence . ControllingClient . Name ;
//return presence.Name;
}
if ( World . GetSceneObjectPart ( key ) ! = null )
{
return World . GetSceneObjectPart ( key ) . Name ;
}
}
return String . Empty ;
}
public void llSetTextureAnim ( int mode , int face , int sizex , int sizey , double start , double length , double rate )
{
m_host . AddScriptLPS ( 1 ) ;
2010-03-06 06:56:55 +00:00
SetTextureAnim ( m_host , mode , face , sizex , sizey , start , length , rate ) ;
}
public void llSetLinkTextureAnim ( int linknumber , int mode , int face , int sizex , int sizey , double start , double length , double rate )
{
m_host . AddScriptLPS ( 1 ) ;
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
2012-08-24 15:41:43 +00:00
foreach ( SceneObjectPart part in parts )
2010-03-06 06:56:55 +00:00
{
SetTextureAnim ( part , mode , face , sizex , sizey , start , length , rate ) ;
}
}
private void SetTextureAnim ( SceneObjectPart part , int mode , int face , int sizex , int sizey , double start , double length , double rate )
{
2008-09-26 02:51:00 +00:00
Primitive . TextureAnimation pTexAnim = new Primitive . TextureAnimation ( ) ;
pTexAnim . Flags = ( Primitive . TextureAnimMode ) mode ;
//ALL_SIDES
if ( face = = ScriptBaseClass . ALL_SIDES )
2010-03-06 06:56:55 +00:00
face = 255 ;
2008-09-26 02:51:00 +00:00
pTexAnim . Face = ( uint ) face ;
pTexAnim . Length = ( float ) length ;
pTexAnim . Rate = ( float ) rate ;
pTexAnim . SizeX = ( uint ) sizex ;
pTexAnim . SizeY = ( uint ) sizey ;
pTexAnim . Start = ( float ) start ;
2010-03-06 06:56:55 +00:00
part . AddTextureAnimation ( pTexAnim ) ;
part . SendFullUpdateToAllClients ( ) ;
part . ParentGroup . HasGroupChanged = true ;
2008-09-26 02:51:00 +00:00
}
public void llTriggerSoundLimited ( string sound , double volume , LSL_Vector top_north_east ,
LSL_Vector bottom_south_west )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-14 21:41:57 +00:00
float radius1 = ( float ) llVecDist ( llGetPos ( ) , top_north_east ) ;
float radius2 = ( float ) llVecDist ( llGetPos ( ) , bottom_south_west ) ;
float radius = Math . Abs ( radius1 - radius2 ) ;
m_host . SendSound ( KeyOrName ( sound ) . ToString ( ) , volume , true , 0 , radius , false , false ) ;
2008-09-26 02:51:00 +00:00
}
public void llEjectFromLand ( string pest )
{
m_host . AddScriptLPS ( 1 ) ;
2012-02-02 23:40:56 +00:00
UUID agentID = new UUID ( ) ;
if ( UUID . TryParse ( pest , out agentID ) )
2008-09-26 02:51:00 +00:00
{
2012-02-02 23:40:56 +00:00
ScenePresence presence = World . GetScenePresence ( agentID ) ;
2008-09-26 02:51:00 +00:00
if ( presence ! = null )
{
// agent must be over the owners land
2012-02-02 23:40:56 +00:00
ILandObject land = World . LandChannel . GetLandObject ( presence . AbsolutePosition . X , presence . AbsolutePosition . Y ) ;
if ( land = = null )
return ;
if ( m_host . OwnerID = = land . LandData . OwnerID )
{
World . TeleportClientHome ( agentID , presence . ControllingClient ) ;
}
2008-09-26 02:51:00 +00:00
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 5000 ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llOverMyLand ( string id )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key = new UUID ( ) ;
2009-03-06 20:44:31 +00:00
if ( UUID . TryParse ( id , out key ) )
2008-09-26 02:51:00 +00:00
{
2009-07-28 09:40:07 +00:00
ScenePresence presence = World . GetScenePresence ( key ) ;
2008-09-26 02:51:00 +00:00
if ( presence ! = null ) // object is an avatar
{
2009-07-28 09:40:07 +00:00
if ( m_host . OwnerID
2009-03-06 20:44:31 +00:00
= = World . LandChannel . GetLandObject (
2009-10-02 09:10:52 +00:00
presence . AbsolutePosition . X , presence . AbsolutePosition . Y ) . LandData . OwnerID )
2008-09-26 02:51:00 +00:00
return 1 ;
}
else // object is not an avatar
{
SceneObjectPart obj = World . GetSceneObjectPart ( key ) ;
if ( obj ! = null )
2009-03-06 20:44:31 +00:00
if ( m_host . OwnerID
= = World . LandChannel . GetLandObject (
2009-10-02 09:10:52 +00:00
obj . AbsolutePosition . X , obj . AbsolutePosition . Y ) . LandData . OwnerID )
2008-09-26 02:51:00 +00:00
return 1 ;
}
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
return 0 ;
}
public LSL_String llGetLandOwnerAt ( LSL_Vector pos )
{
m_host . AddScriptLPS ( 1 ) ;
2010-05-10 02:57:17 +00:00
ILandObject land = World . LandChannel . GetLandObject ( ( float ) pos . x , ( float ) pos . y ) ;
if ( land = = null )
return UUID . Zero . ToString ( ) ;
return land . LandData . OwnerID . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
2008-10-13 20:56:56 +00:00
/// <summary>
/// According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize
2009-07-28 09:40:07 +00:00
/// only the height of avatars vary and that says:
2008-10-13 20:56:56 +00:00
/// Width (x) and depth (y) are constant. (0.45m and 0.6m respectively).
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Vector llGetAgentSize ( string id )
{
m_host . AddScriptLPS ( 1 ) ;
2008-09-26 17:25:22 +00:00
ScenePresence avatar = World . GetScenePresence ( ( UUID ) id ) ;
2008-09-26 02:51:00 +00:00
LSL_Vector agentSize ;
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
if ( avatar = = null | | avatar . IsChildAgent ) // Fail if not in the same region
2008-09-26 02:51:00 +00:00
{
agentSize = ScriptBaseClass . ZERO_VECTOR ;
}
else
{
2008-12-01 00:49:36 +00:00
agentSize = new LSL_Vector ( 0.45 , 0.6 , avatar . Appearance . AvatarHeight ) ;
2008-09-26 02:51:00 +00:00
}
return agentSize ;
}
public LSL_Integer llSameGroup ( string agent )
{
m_host . AddScriptLPS ( 1 ) ;
UUID agentId = new UUID ( ) ;
if ( ! UUID . TryParse ( agent , out agentId ) )
return new LSL_Integer ( 0 ) ;
ScenePresence presence = World . GetScenePresence ( agentId ) ;
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
if ( presence = = null | | presence . IsChildAgent ) // Return flase for child agents
2008-09-26 02:51:00 +00:00
return new LSL_Integer ( 0 ) ;
IClientAPI client = presence . ControllingClient ;
if ( m_host . GroupID = = client . ActiveGroupId )
return new LSL_Integer ( 1 ) ;
else
return new LSL_Integer ( 0 ) ;
}
public void llUnSit ( string id )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key = new UUID ( ) ;
if ( UUID . TryParse ( id , out key ) )
{
ScenePresence av = World . GetScenePresence ( key ) ;
if ( av ! = null )
{
if ( llAvatarOnSitTarget ( ) = = id )
{
// if the avatar is sitting on this object, then
// we can unsit them. We don't want random scripts unsitting random people
// Lets avoid the popcorn avatar scenario.
av . StandUp ( ) ;
}
else
{
// If the object owner also owns the parcel
// or
// if the land is group owned and the object is group owned by the same group
// or
// if the object is owned by a person with estate access.
ILandObject parcel = World . LandChannel . GetLandObject ( av . AbsolutePosition . X , av . AbsolutePosition . Y ) ;
if ( parcel ! = null )
{
2009-10-15 23:35:27 +00:00
if ( m_host . OwnerID = = parcel . LandData . OwnerID | |
2009-10-02 09:10:52 +00:00
( m_host . OwnerID = = m_host . GroupID & & m_host . GroupID = = parcel . LandData . GroupID
& & parcel . LandData . IsGroupOwned ) | | World . Permissions . IsGod ( m_host . OwnerID ) )
2008-09-26 02:51:00 +00:00
{
av . StandUp ( ) ;
}
}
}
}
}
}
public LSL_Vector llGroundSlope ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
2009-06-03 05:31:53 +00:00
//Get the slope normal. This gives us the equation of the plane tangent to the slope.
LSL_Vector vsn = llGroundNormal ( offset ) ;
2008-09-26 02:51:00 +00:00
2009-06-03 05:31:53 +00:00
//Plug the x,y coordinates of the slope normal into the equation of the plane to get
//the height of that point on the plane. The resulting vector gives the slope.
2012-08-18 00:17:01 +00:00
Vector3 vsl = vsn ;
2009-06-03 05:31:53 +00:00
vsl . Z = ( float ) ( ( ( vsn . x * vsn . x ) + ( vsn . y * vsn . y ) ) / ( - 1 * vsn . z ) ) ;
vsl . Normalize ( ) ;
//Normalization might be overkill here
return new LSL_Vector ( vsl . X , vsl . Y , vsl . Z ) ;
}
public LSL_Vector llGroundNormal ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
Vector3 pos = m_host . GetWorldPosition ( ) + ( Vector3 ) offset ;
2009-06-03 05:31:53 +00:00
// Clamp to valid position
if ( pos . X < 0 )
pos . X = 0 ;
else if ( pos . X > = World . Heightmap . Width )
pos . X = World . Heightmap . Width - 1 ;
if ( pos . Y < 0 )
pos . Y = 0 ;
else if ( pos . Y > = World . Heightmap . Height )
pos . Y = World . Heightmap . Height - 1 ;
//Find two points in addition to the position to define a plane
2008-09-26 02:51:00 +00:00
Vector3 p0 = new Vector3 ( pos . X , pos . Y ,
2009-06-03 05:31:53 +00:00
( float ) World . Heightmap [ ( int ) pos . X , ( int ) pos . Y ] ) ;
Vector3 p1 = new Vector3 ( ) ;
Vector3 p2 = new Vector3 ( ) ;
if ( ( pos . X + 1.0f ) > = World . Heightmap . Width )
p1 = new Vector3 ( pos . X + 1.0f , pos . Y ,
( float ) World . Heightmap [ ( int ) pos . X , ( int ) pos . Y ] ) ;
else
p1 = new Vector3 ( pos . X + 1.0f , pos . Y ,
( float ) World . Heightmap [ ( int ) ( pos . X + 1.0f ) , ( int ) pos . Y ] ) ;
if ( ( pos . Y + 1.0f ) > = World . Heightmap . Height )
p2 = new Vector3 ( pos . X , pos . Y + 1.0f ,
( float ) World . Heightmap [ ( int ) pos . X , ( int ) pos . Y ] ) ;
else
p2 = new Vector3 ( pos . X , pos . Y + 1.0f ,
( float ) World . Heightmap [ ( int ) pos . X , ( int ) ( pos . Y + 1.0f ) ] ) ;
2008-09-26 02:51:00 +00:00
2009-06-03 05:31:53 +00:00
//Find normalized vectors from p0 to p1 and p0 to p2
2008-10-07 11:41:43 +00:00
Vector3 v0 = new Vector3 ( p1 . X - p0 . X , p1 . Y - p0 . Y , p1 . Z - p0 . Z ) ;
2009-06-03 05:31:53 +00:00
Vector3 v1 = new Vector3 ( p2 . X - p0 . X , p2 . Y - p0 . Y , p2 . Z - p0 . Z ) ;
2008-09-26 02:51:00 +00:00
v0 . Normalize ( ) ;
v1 . Normalize ( ) ;
2009-06-03 05:31:53 +00:00
//Find the cross product of the vectors (the slope normal).
Vector3 vsn = new Vector3 ( ) ;
vsn . X = ( v0 . Y * v1 . Z ) - ( v0 . Z * v1 . Y ) ;
vsn . Y = ( v0 . Z * v1 . X ) - ( v0 . X * v1 . Z ) ;
vsn . Z = ( v0 . X * v1 . Y ) - ( v0 . Y * v1 . X ) ;
vsn . Normalize ( ) ;
//I believe the crossproduct of two normalized vectors is a normalized vector so
//this normalization may be overkill
2008-09-26 02:51:00 +00:00
2009-06-03 05:31:53 +00:00
return new LSL_Vector ( vsn . X , vsn . Y , vsn . Z ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGroundContour ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
LSL_Vector x = llGroundSlope ( offset ) ;
return new LSL_Vector ( - x . y , x . x , 0.0 ) ;
}
public LSL_Integer llGetAttached ( )
{
m_host . AddScriptLPS ( 1 ) ;
2011-08-26 23:15:21 +00:00
return m_host . ParentGroup . AttachmentPoint ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llGetFreeMemory ( )
{
m_host . AddScriptLPS ( 1 ) ;
// Make scripts designed for LSO happy
return 16384 ;
}
2009-05-13 01:47:29 +00:00
public LSL_Integer llGetFreeURLs ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-05-13 04:04:26 +00:00
if ( m_UrlModule ! = null )
return new LSL_Integer ( m_UrlModule . GetFreeUrls ( ) ) ;
2009-05-13 01:47:29 +00:00
return new LSL_Integer ( 0 ) ;
}
2008-09-26 02:51:00 +00:00
public LSL_String llGetRegionName ( )
{
m_host . AddScriptLPS ( 1 ) ;
return World . RegionInfo . RegionName ;
}
public LSL_Float llGetRegionTimeDilation ( )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) World . TimeDilation ;
}
2008-10-16 13:17:31 +00:00
/// <summary>
/// Returns the value reported in the client Statistics window
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Float llGetRegionFPS ( )
{
m_host . AddScriptLPS ( 1 ) ;
2011-10-10 21:23:42 +00:00
return World . StatsReporter . LastReportedSimFPS ;
2008-09-26 02:51:00 +00:00
}
2010-09-24 14:26:53 +00:00
2008-09-26 02:51:00 +00:00
/ * particle system rules should be coming into this routine as doubles , that is
rule [ 0 ] should be an integer from this list and rule [ 1 ] should be the arg
for the same integer . wiki . secondlife . com has most of this mapping , but some
came from http : //www.caligari-designs.com/p4u2
We iterate through the list for ' Count ' elements , incrementing by two for each
iteration and set the members of Primitive . ParticleSystem , one at a time .
* /
public enum PrimitiveRule : int
{
PSYS_PART_FLAGS = 0 ,
PSYS_PART_START_COLOR = 1 ,
PSYS_PART_START_ALPHA = 2 ,
PSYS_PART_END_COLOR = 3 ,
PSYS_PART_END_ALPHA = 4 ,
PSYS_PART_START_SCALE = 5 ,
PSYS_PART_END_SCALE = 6 ,
PSYS_PART_MAX_AGE = 7 ,
PSYS_SRC_ACCEL = 8 ,
PSYS_SRC_PATTERN = 9 ,
2010-07-16 23:35:51 +00:00
PSYS_SRC_INNERANGLE = 10 ,
PSYS_SRC_OUTERANGLE = 11 ,
2008-09-26 02:51:00 +00:00
PSYS_SRC_TEXTURE = 12 ,
PSYS_SRC_BURST_RATE = 13 ,
PSYS_SRC_BURST_PART_COUNT = 15 ,
PSYS_SRC_BURST_RADIUS = 16 ,
PSYS_SRC_BURST_SPEED_MIN = 17 ,
PSYS_SRC_BURST_SPEED_MAX = 18 ,
PSYS_SRC_MAX_AGE = 19 ,
PSYS_SRC_TARGET_KEY = 20 ,
PSYS_SRC_OMEGA = 21 ,
PSYS_SRC_ANGLE_BEGIN = 22 ,
PSYS_SRC_ANGLE_END = 23
}
internal Primitive . ParticleSystem . ParticleDataFlags ConvertUINTtoFlags ( uint flags )
{
Primitive . ParticleSystem . ParticleDataFlags returnval = Primitive . ParticleSystem . ParticleDataFlags . None ;
return returnval ;
}
2009-07-06 13:09:03 +00:00
protected Primitive . ParticleSystem getNewParticleSystemWithSLDefaultValues ( )
2008-09-26 02:51:00 +00:00
{
Primitive . ParticleSystem ps = new Primitive . ParticleSystem ( ) ;
// TODO find out about the other defaults and add them here
ps . PartStartColor = new Color4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
ps . PartEndColor = new Color4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
ps . PartStartScaleX = 1.0f ;
ps . PartStartScaleY = 1.0f ;
ps . PartEndScaleX = 1.0f ;
ps . PartEndScaleY = 1.0f ;
ps . BurstSpeedMin = 1.0f ;
ps . BurstSpeedMax = 1.0f ;
ps . BurstRate = 0.1f ;
ps . PartMaxAge = 10.0f ;
return ps ;
}
2010-03-06 06:56:55 +00:00
public void llLinkParticleSystem ( int linknumber , LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
2012-08-24 15:41:43 +00:00
foreach ( SceneObjectPart part in parts )
2010-03-06 06:56:55 +00:00
{
SetParticleSystem ( part , rules ) ;
}
}
2008-09-26 02:51:00 +00:00
public void llParticleSystem ( LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
2010-03-06 06:56:55 +00:00
SetParticleSystem ( m_host , rules ) ;
}
private void SetParticleSystem ( SceneObjectPart part , LSL_List rules ) {
2010-09-24 14:26:53 +00:00
2008-09-26 02:51:00 +00:00
if ( rules . Length = = 0 )
{
2010-03-06 06:56:55 +00:00
part . RemoveParticleSystem ( ) ;
part . ParentGroup . HasGroupChanged = true ;
2008-09-26 02:51:00 +00:00
}
else
{
Primitive . ParticleSystem prules = getNewParticleSystemWithSLDefaultValues ( ) ;
LSL_Vector tempv = new LSL_Vector ( ) ;
float tempf = 0 ;
for ( int i = 0 ; i < rules . Length ; i + = 2 )
{
2010-03-07 16:05:24 +00:00
switch ( rules . GetLSLIntegerItem ( i ) )
2008-09-26 02:51:00 +00:00
{
case ( int ) ScriptBaseClass . PSYS_PART_FLAGS :
prules . PartDataFlags = ( Primitive . ParticleSystem . ParticleDataFlags ) ( uint ) rules . GetLSLIntegerItem ( i + 1 ) ;
break ;
case ( int ) ScriptBaseClass . PSYS_PART_START_COLOR :
tempv = rules . GetVector3Item ( i + 1 ) ;
prules . PartStartColor . R = ( float ) tempv . x ;
prules . PartStartColor . G = ( float ) tempv . y ;
prules . PartStartColor . B = ( float ) tempv . z ;
break ;
case ( int ) ScriptBaseClass . PSYS_PART_START_ALPHA :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . PartStartColor . A = tempf ;
break ;
case ( int ) ScriptBaseClass . PSYS_PART_END_COLOR :
tempv = rules . GetVector3Item ( i + 1 ) ;
prules . PartEndColor . R = ( float ) tempv . x ;
prules . PartEndColor . G = ( float ) tempv . y ;
prules . PartEndColor . B = ( float ) tempv . z ;
break ;
case ( int ) ScriptBaseClass . PSYS_PART_END_ALPHA :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . PartEndColor . A = tempf ;
break ;
case ( int ) ScriptBaseClass . PSYS_PART_START_SCALE :
tempv = rules . GetVector3Item ( i + 1 ) ;
prules . PartStartScaleX = ( float ) tempv . x ;
prules . PartStartScaleY = ( float ) tempv . y ;
break ;
case ( int ) ScriptBaseClass . PSYS_PART_END_SCALE :
tempv = rules . GetVector3Item ( i + 1 ) ;
prules . PartEndScaleX = ( float ) tempv . x ;
prules . PartEndScaleY = ( float ) tempv . y ;
break ;
case ( int ) ScriptBaseClass . PSYS_PART_MAX_AGE :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . PartMaxAge = tempf ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_ACCEL :
tempv = rules . GetVector3Item ( i + 1 ) ;
prules . PartAcceleration . X = ( float ) tempv . x ;
prules . PartAcceleration . Y = ( float ) tempv . y ;
prules . PartAcceleration . Z = ( float ) tempv . z ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_PATTERN :
int tmpi = ( int ) rules . GetLSLIntegerItem ( i + 1 ) ;
prules . Pattern = ( Primitive . ParticleSystem . SourcePattern ) tmpi ;
break ;
2010-07-16 23:35:51 +00:00
// PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The
// PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The
// client tells the difference between the two by looking at the 0x02 bit in
// the PartFlags variable.
case ( int ) ScriptBaseClass . PSYS_SRC_INNERANGLE :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . InnerAngle = ( float ) tempf ;
prules . PartFlags & = 0xFFFFFFFD ; // Make sure new angle format is off.
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_OUTERANGLE :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . OuterAngle = ( float ) tempf ;
prules . PartFlags & = 0xFFFFFFFD ; // Make sure new angle format is off.
break ;
2008-09-26 02:51:00 +00:00
case ( int ) ScriptBaseClass . PSYS_SRC_TEXTURE :
prules . Texture = KeyOrName ( rules . GetLSLStringItem ( i + 1 ) ) ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_BURST_RATE :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . BurstRate = ( float ) tempf ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_BURST_PART_COUNT :
prules . BurstPartCount = ( byte ) ( int ) rules . GetLSLIntegerItem ( i + 1 ) ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_BURST_RADIUS :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . BurstRadius = ( float ) tempf ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_BURST_SPEED_MIN :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . BurstSpeedMin = ( float ) tempf ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_BURST_SPEED_MAX :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . BurstSpeedMax = ( float ) tempf ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_MAX_AGE :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . MaxAge = ( float ) tempf ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_TARGET_KEY :
UUID key = UUID . Zero ;
if ( UUID . TryParse ( rules . Data [ i + 1 ] . ToString ( ) , out key ) )
{
prules . Target = key ;
}
else
{
2010-03-06 06:56:55 +00:00
prules . Target = part . UUID ;
2008-09-26 02:51:00 +00:00
}
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_OMEGA :
// AL: This is an assumption, since it is the only thing that would match.
tempv = rules . GetVector3Item ( i + 1 ) ;
prules . AngularVelocity . X = ( float ) tempv . x ;
prules . AngularVelocity . Y = ( float ) tempv . y ;
prules . AngularVelocity . Z = ( float ) tempv . z ;
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_ANGLE_BEGIN :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . InnerAngle = ( float ) tempf ;
2010-07-16 23:35:51 +00:00
prules . PartFlags | = 0x02 ; // Set new angle format.
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PSYS_SRC_ANGLE_END :
tempf = ( float ) rules . GetLSLFloatItem ( i + 1 ) ;
prules . OuterAngle = ( float ) tempf ;
2010-07-16 23:35:51 +00:00
prules . PartFlags | = 0x02 ; // Set new angle format.
2008-09-26 02:51:00 +00:00
break ;
}
}
prules . CRC = 1 ;
2010-03-06 06:56:55 +00:00
part . AddNewParticleSystem ( prules ) ;
part . ParentGroup . HasGroupChanged = true ;
2008-09-26 02:51:00 +00:00
}
2010-03-06 06:56:55 +00:00
part . SendFullUpdateToAllClients ( ) ;
2008-09-26 02:51:00 +00:00
}
public void llGroundRepel ( double height , int water , double tau )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-14 21:41:57 +00:00
if ( m_host . PhysActor ! = null )
{
float ground = ( float ) llGround ( new LSL_Types . Vector3 ( 0 , 0 , 0 ) ) ;
2010-09-24 14:26:53 +00:00
float waterLevel = ( float ) llWater ( new LSL_Types . Vector3 ( 0 , 0 , 0 ) ) ;
2010-02-14 21:41:57 +00:00
PIDHoverType hoverType = PIDHoverType . Ground ;
if ( water ! = 0 )
{
hoverType = PIDHoverType . GroundAndWater ;
if ( ground < waterLevel )
height + = waterLevel ;
else
height + = ground ;
}
else
{
height + = ground ;
}
2010-09-24 14:26:53 +00:00
2010-02-14 21:41:57 +00:00
m_host . SetHoverHeight ( ( float ) height , hoverType , ( float ) tau ) ;
}
2008-09-26 02:51:00 +00:00
}
public void llGiveInventoryList ( string destination , string category , LSL_List inventory )
{
m_host . AddScriptLPS ( 1 ) ;
UUID destID ;
if ( ! UUID . TryParse ( destination , out destID ) )
return ;
List < UUID > itemList = new List < UUID > ( ) ;
foreach ( Object item in inventory . Data )
{
2012-07-04 20:33:35 +00:00
string rawItemString = item . ToString ( ) ;
2008-09-26 02:51:00 +00:00
UUID itemID ;
2012-07-04 20:33:35 +00:00
if ( UUID . TryParse ( rawItemString , out itemID ) )
2008-09-26 02:51:00 +00:00
{
itemList . Add ( itemID ) ;
}
else
{
2012-07-04 20:33:35 +00:00
TaskInventoryItem taskItem = m_host . Inventory . GetInventoryItem ( rawItemString ) ;
if ( taskItem ! = null )
itemList . Add ( taskItem . ItemID ) ;
2008-09-26 02:51:00 +00:00
}
}
if ( itemList . Count = = 0 )
return ;
2008-12-14 22:27:40 +00:00
UUID folderID = m_ScriptEngine . World . MoveTaskInventoryItems ( destID , category , m_host , itemList ) ;
if ( folderID = = UUID . Zero )
return ;
if ( m_TransferModule ! = null )
2012-07-17 22:31:38 +00:00
{
byte [ ] bucket = new byte [ ] { ( byte ) AssetType . Folder } ;
GridInstantMessage msg = new GridInstantMessage ( World ,
m_host . UUID , m_host . Name + ", an object owned by " +
resolveName ( m_host . OwnerID ) + "," , destID ,
( byte ) InstantMessageDialog . TaskInventoryOffered ,
false , category + "\n" + m_host . Name + " is located at " +
World . RegionInfo . RegionName + " " +
m_host . AbsolutePosition . ToString ( ) ,
folderID , true , m_host . AbsolutePosition ,
bucket ) ;
2009-06-10 04:28:56 +00:00
m_TransferModule . SendInstantMessage ( msg , delegate ( bool success ) { } ) ;
2012-07-17 22:31:38 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llSetVehicleType ( int type )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2008-09-28 22:38:59 +00:00
{
2011-09-01 00:22:28 +00:00
m_host . ParentGroup . RootPart . SetVehicleType ( type ) ;
2008-09-28 22:38:59 +00:00
}
2008-09-26 02:51:00 +00:00
}
2008-09-28 21:53:56 +00:00
//CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
//CFK 9/28: so these are not complete yet.
2008-10-20 07:47:20 +00:00
public void llSetVehicleFloatParam ( int param , LSL_Float value )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2008-09-28 18:36:30 +00:00
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2008-09-28 18:36:30 +00:00
{
2011-09-01 00:22:28 +00:00
m_host . ParentGroup . RootPart . SetVehicleFloatParam ( param , ( float ) value ) ;
2008-09-28 18:36:30 +00:00
}
2008-09-26 02:51:00 +00:00
}
2008-09-28 21:53:56 +00:00
//CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
//CFK 9/28: so these are not complete yet.
2008-09-26 02:51:00 +00:00
public void llSetVehicleVectorParam ( int param , LSL_Vector vec )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2008-09-28 21:20:25 +00:00
{
2012-08-18 00:17:01 +00:00
m_host . ParentGroup . RootPart . SetVehicleVectorParam ( param , vec ) ;
2008-09-28 21:20:25 +00:00
}
2008-09-26 02:51:00 +00:00
}
2008-09-28 21:53:56 +00:00
//CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
//CFK 9/28: so these are not complete yet.
2008-09-26 02:51:00 +00:00
public void llSetVehicleRotationParam ( int param , LSL_Rotation rot )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2008-09-28 21:53:56 +00:00
{
2012-08-18 14:18:31 +00:00
m_host . ParentGroup . RootPart . SetVehicleRotationParam ( param , rot ) ;
2008-09-28 21:53:56 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llSetVehicleFlags ( int flags )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2010-02-14 21:41:57 +00:00
{
2011-09-01 00:22:28 +00:00
m_host . ParentGroup . RootPart . SetVehicleFlags ( flags , false ) ;
2010-02-14 21:41:57 +00:00
}
2008-09-26 02:51:00 +00:00
}
public void llRemoveVehicleFlags ( int flags )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
2010-02-14 21:41:57 +00:00
{
2011-09-01 00:22:28 +00:00
m_host . ParentGroup . RootPart . SetVehicleFlags ( flags , true ) ;
2010-02-14 21:41:57 +00:00
}
2008-09-26 02:51:00 +00:00
}
2012-02-22 19:15:42 +00:00
protected void SitTarget ( SceneObjectPart part , LSL_Vector offset , LSL_Rotation rot )
2008-09-26 02:51:00 +00:00
{
2012-08-18 00:17:01 +00:00
part . SitTargetPosition = offset ;
2012-08-18 14:19:15 +00:00
part . SitTargetOrientation = rot ;
2012-02-22 19:15:42 +00:00
part . ParentGroup . HasGroupChanged = true ;
}
public void llSitTarget ( LSL_Vector offset , LSL_Rotation rot )
{
m_host . AddScriptLPS ( 1 ) ;
SitTarget ( m_host , offset , rot ) ;
}
public void llLinkSitTarget ( LSL_Integer link , LSL_Vector offset , LSL_Rotation rot )
{
m_host . AddScriptLPS ( 1 ) ;
if ( link = = ScriptBaseClass . LINK_ROOT )
SitTarget ( m_host . ParentGroup . RootPart , offset , rot ) ;
else if ( link = = ScriptBaseClass . LINK_THIS )
SitTarget ( m_host , offset , rot ) ;
else
{
SceneObjectPart part = m_host . ParentGroup . GetLinkNumPart ( link ) ;
if ( null ! = part )
{
SitTarget ( part , offset , rot ) ;
}
}
2008-09-26 02:51:00 +00:00
}
public LSL_String llAvatarOnSitTarget ( )
{
m_host . AddScriptLPS ( 1 ) ;
2011-10-17 01:04:20 +00:00
return m_host . SitTargetAvatar . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
2011-09-26 18:18:06 +00:00
// http://wiki.secondlife.com/wiki/LlAvatarOnLinkSitTarget
public LSL_String llAvatarOnLinkSitTarget ( int linknum )
{
m_host . AddScriptLPS ( 1 ) ;
if ( linknum = = ScriptBaseClass . LINK_SET | |
linknum = = ScriptBaseClass . LINK_ALL_CHILDREN | |
linknum = = ScriptBaseClass . LINK_ALL_OTHERS ) return UUID . Zero . ToString ( ) ;
List < SceneObjectPart > parts = GetLinkParts ( linknum ) ;
if ( parts . Count = = 0 ) return UUID . Zero . ToString ( ) ;
return parts [ 0 ] . SitTargetAvatar . ToString ( ) ;
}
2008-09-26 02:51:00 +00:00
public void llAddToLandPassList ( string avatar , double hours )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key ;
2010-12-13 20:35:56 +00:00
ILandObject land = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) ;
2012-02-02 23:40:56 +00:00
if ( World . Permissions . CanEditParcelProperties ( m_host . OwnerID , land , GroupPowers . LandManageBanned ) )
2008-09-26 02:51:00 +00:00
{
2012-02-02 23:40:56 +00:00
int expires = 0 ;
if ( hours ! = 0 )
expires = Util . UnixTimeSinceEpoch ( ) + ( int ) ( 3600.0 * hours ) ;
2008-09-26 02:51:00 +00:00
if ( UUID . TryParse ( avatar , out key ) )
{
2012-02-02 23:40:56 +00:00
int idx = land . LandData . ParcelAccessList . FindIndex (
delegate ( LandAccessEntry e )
2010-12-13 20:35:56 +00:00
{
if ( e . AgentID = = key & & e . Flags = = AccessList . Access )
return true ;
return false ;
2012-02-02 23:40:56 +00:00
} ) ;
if ( idx ! = - 1 & & ( land . LandData . ParcelAccessList [ idx ] . Expires = = 0 | | ( expires ! = 0 & & expires < land . LandData . ParcelAccessList [ idx ] . Expires ) ) )
return ;
if ( idx ! = - 1 )
land . LandData . ParcelAccessList . RemoveAt ( idx ) ;
LandAccessEntry entry = new LandAccessEntry ( ) ;
entry . AgentID = key ;
entry . Flags = AccessList . Access ;
entry . Expires = expires ;
land . LandData . ParcelAccessList . Add ( entry ) ;
World . EventManager . TriggerLandObjectUpdated ( ( uint ) land . LandData . LocalID , land ) ;
2008-09-26 02:51:00 +00:00
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetTouchText ( string text )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . TouchName = text ;
}
public void llSetSitText ( string text )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . SitName = text ;
}
public void llSetCameraEyeOffset ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
m_host . SetCameraEyeOffset ( offset ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetCameraAtOffset ( LSL_Vector offset )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
m_host . SetCameraAtOffset ( offset ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llDumpList2String ( LSL_List src , string seperator )
{
m_host . AddScriptLPS ( 1 ) ;
if ( src . Length = = 0 )
{
return String . Empty ;
}
string ret = String . Empty ;
foreach ( object o in src . Data )
{
ret = ret + o . ToString ( ) + seperator ;
}
ret = ret . Substring ( 0 , ret . Length - seperator . Length ) ;
return ret ;
}
public LSL_Integer llScriptDanger ( LSL_Vector pos )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
bool result = World . ScriptDanger ( m_host . LocalId , pos ) ;
2008-09-26 02:51:00 +00:00
if ( result )
{
return 1 ;
}
else
{
return 0 ;
}
}
public void llDialog ( string avatar , string message , LSL_List buttons , int chat_channel )
{
2009-01-08 19:14:52 +00:00
IDialogModule dm = World . RequestModuleInterface < IDialogModule > ( ) ;
2009-07-28 09:40:07 +00:00
2009-01-08 19:14:52 +00:00
if ( dm = = null )
return ;
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
UUID av = new UUID ( ) ;
if ( ! UUID . TryParse ( avatar , out av ) )
{
LSLError ( "First parameter to llDialog needs to be a key" ) ;
return ;
}
2009-12-30 00:36:16 +00:00
if ( buttons . Length < 1 )
{
LSLError ( "No less than 1 button can be shown" ) ;
return ;
}
2008-09-26 02:51:00 +00:00
if ( buttons . Length > 12 )
{
LSLError ( "No more than 12 buttons can be shown" ) ;
return ;
}
string [ ] buts = new string [ buttons . Length ] ;
for ( int i = 0 ; i < buttons . Length ; i + + )
{
if ( buttons . Data [ i ] . ToString ( ) = = String . Empty )
{
LSLError ( "button label cannot be blank" ) ;
return ;
}
if ( buttons . Data [ i ] . ToString ( ) . Length > 24 )
{
LSLError ( "button label cannot be longer than 24 characters" ) ;
return ;
}
buts [ i ] = buttons . Data [ i ] . ToString ( ) ;
}
2009-07-28 09:40:07 +00:00
2009-01-08 19:14:52 +00:00
dm . SendDialogToUser (
2009-07-28 09:40:07 +00:00
av , m_host . Name , m_host . UUID , m_host . OwnerID ,
2009-01-08 19:14:52 +00:00
message , new UUID ( "00000000-0000-2222-3333-100000001000" ) , chat_channel , buts ) ;
2009-07-28 09:40:07 +00:00
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
}
public void llVolumeDetect ( int detect )
{
m_host . AddScriptLPS ( 1 ) ;
2011-09-01 00:22:28 +00:00
if ( ! m_host . ParentGroup . IsDeleted )
m_host . ParentGroup . ScriptSetVolumeDetect ( detect ! = 0 ) ;
2008-09-26 02:51:00 +00:00
}
/// <summary>
2008-09-29 20:24:59 +00:00
/// This is a depecated function so this just replicates the result of
/// invoking it in SL
2008-09-26 02:51:00 +00:00
/// </summary>
2008-09-29 20:24:59 +00:00
public void llRemoteLoadScript ( string target , string name , int running , int start_param )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2008-09-29 20:24:59 +00:00
// Report an error as it does in SL
ShoutError ( "Deprecated. Please use llRemoteLoadScriptPin instead." ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 3000 ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetRemoteScriptAccessPin ( int pin )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . ScriptAccessPin = pin ;
}
public void llRemoteLoadScriptPin ( string target , string name , int pin , int running , int start_param )
{
m_host . AddScriptLPS ( 1 ) ;
2012-07-04 20:42:04 +00:00
2008-09-26 02:51:00 +00:00
UUID destId = UUID . Zero ;
if ( ! UUID . TryParse ( target , out destId ) )
{
llSay ( 0 , "Could not parse key " + target ) ;
return ;
}
// target must be a different prim than the one containing the script
if ( m_host . UUID = = destId )
{
return ;
}
// copy the first script found with this inventory name
2012-07-04 20:36:44 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( name ) ;
2008-09-26 02:51:00 +00:00
2012-07-04 20:36:44 +00:00
// make sure the object is a script
if ( item = = null | | item . Type ! = 10 )
2008-09-26 02:51:00 +00:00
{
llSay ( 0 , "Could not find script " + name ) ;
return ;
}
// the rest of the permission checks are done in RezScript, so check the pin there as well
2012-07-04 20:36:44 +00:00
World . RezScriptFromPrim ( item . ItemID , m_host , destId , pin , running , start_param ) ;
2012-01-25 23:22:07 +00:00
2008-09-26 02:51:00 +00:00
// this will cause the delay even if the script pin or permissions were wrong - seems ok
ScriptSleep ( 3000 ) ;
}
public void llOpenRemoteDataChannel ( )
{
m_host . AddScriptLPS ( 1 ) ;
IXMLRPC xmlrpcMod = m_ScriptEngine . World . RequestModuleInterface < IXMLRPC > ( ) ;
if ( xmlrpcMod . IsEnabled ( ) )
{
2012-05-08 22:20:27 +00:00
UUID channelID = xmlrpcMod . OpenXMLRPCChannel ( m_host . LocalId , m_item . ItemID , UUID . Zero ) ;
2009-04-10 21:08:33 +00:00
IXmlRpcRouter xmlRpcRouter = m_ScriptEngine . World . RequestModuleInterface < IXmlRpcRouter > ( ) ;
if ( xmlRpcRouter ! = null )
2009-09-18 20:32:46 +00:00
{
string ExternalHostName = m_ScriptEngine . World . RegionInfo . ExternalHostName ;
2010-09-24 14:26:53 +00:00
xmlRpcRouter . RegisterNewReceiver ( m_ScriptEngine . ScriptModule , channelID , m_host . UUID ,
2012-05-08 21:58:34 +00:00
m_item . ItemID , String . Format ( "http://{0}:{1}/" , ExternalHostName ,
2009-09-16 14:33:42 +00:00
xmlrpcMod . Port . ToString ( ) ) ) ;
2009-09-18 20:32:46 +00:00
}
2010-09-24 14:26:53 +00:00
object [ ] resobj = new object [ ]
{
new LSL_Integer ( 1 ) ,
new LSL_String ( channelID . ToString ( ) ) ,
new LSL_String ( UUID . Zero . ToString ( ) ) ,
new LSL_String ( String . Empty ) ,
new LSL_Integer ( 0 ) ,
new LSL_String ( String . Empty )
2009-09-16 14:33:42 +00:00
} ;
2012-05-08 21:58:34 +00:00
m_ScriptEngine . PostScriptEvent ( m_item . ItemID , new EventParams ( "remote_data" , resobj ,
2009-09-16 14:33:42 +00:00
new DetectParams [ 0 ] ) ) ;
2008-09-26 02:51:00 +00:00
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llSendRemoteData ( string channel , string dest , int idata , string sdata )
{
m_host . AddScriptLPS ( 1 ) ;
IXMLRPC xmlrpcMod = m_ScriptEngine . World . RequestModuleInterface < IXMLRPC > ( ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 3000 ) ;
2012-05-08 22:20:27 +00:00
return ( xmlrpcMod . SendRemoteData ( m_host . LocalId , m_item . ItemID , channel , dest , idata , sdata ) ) . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public void llRemoteDataReply ( string channel , string message_id , string sdata , int idata )
{
m_host . AddScriptLPS ( 1 ) ;
IXMLRPC xmlrpcMod = m_ScriptEngine . World . RequestModuleInterface < IXMLRPC > ( ) ;
xmlrpcMod . RemoteDataReply ( channel , message_id , sdata , idata ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 3000 ) ;
2008-09-26 02:51:00 +00:00
}
public void llCloseRemoteDataChannel ( string channel )
{
m_host . AddScriptLPS ( 1 ) ;
IXMLRPC xmlrpcMod = m_ScriptEngine . World . RequestModuleInterface < IXMLRPC > ( ) ;
2008-09-26 17:25:22 +00:00
xmlrpcMod . CloseXMLRPCChannel ( ( UUID ) channel ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llMD5String ( string src , int nonce )
{
m_host . AddScriptLPS ( 1 ) ;
2009-09-16 14:33:42 +00:00
return Util . Md5Hash ( String . Format ( "{0}:{1}" , src , nonce . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
}
2009-01-28 04:50:25 +00:00
public LSL_String llSHA1String ( string src )
{
m_host . AddScriptLPS ( 1 ) ;
2009-01-29 19:47:55 +00:00
return Util . SHA1Hash ( src ) . ToLower ( ) ;
2009-01-28 04:50:25 +00:00
}
2009-01-29 19:47:55 +00:00
2011-08-25 01:21:51 +00:00
protected ObjectShapePacket . ObjectDataBlock SetPrimitiveBlockShapeParams ( SceneObjectPart part , int holeshape , LSL_Vector cut , float hollow , LSL_Vector twist , byte profileshape , byte pathcurve )
2008-09-26 02:51:00 +00:00
{
2011-09-04 17:21:29 +00:00
float tempFloat ; // Use in float expressions below to avoid byte cast precision issues.
2008-09-26 02:51:00 +00:00
ObjectShapePacket . ObjectDataBlock shapeBlock = new ObjectShapePacket . ObjectDataBlock ( ) ;
if ( holeshape ! = ( int ) ScriptBaseClass . PRIM_HOLE_DEFAULT & &
holeshape ! = ( int ) ScriptBaseClass . PRIM_HOLE_CIRCLE & &
holeshape ! = ( int ) ScriptBaseClass . PRIM_HOLE_SQUARE & &
holeshape ! = ( int ) ScriptBaseClass . PRIM_HOLE_TRIANGLE )
{
holeshape = ( int ) ScriptBaseClass . PRIM_HOLE_DEFAULT ;
}
2011-08-25 01:21:51 +00:00
shapeBlock . PathCurve = pathcurve ;
shapeBlock . ProfileCurve = ( byte ) holeshape ; // Set the hole shape.
shapeBlock . ProfileCurve + = profileshape ; // Add in the profile shape.
2008-09-26 02:51:00 +00:00
if ( cut . x < 0f )
{
cut . x = 0f ;
}
if ( cut . x > 1f )
{
cut . x = 1f ;
}
if ( cut . y < 0f )
{
cut . y = 0f ;
}
if ( cut . y > 1f )
{
cut . y = 1f ;
2010-06-25 12:15:26 +00:00
}
if ( cut . y - cut . x < 0.05f )
{
cut . x = cut . y - 0.05f ;
if ( cut . x < 0.0f )
{
cut . x = 0.0f ;
cut . y = 0.05f ;
}
2008-09-26 02:51:00 +00:00
}
shapeBlock . ProfileBegin = ( ushort ) ( 50000 * cut . x ) ;
shapeBlock . ProfileEnd = ( ushort ) ( 50000 * ( 1 - cut . y ) ) ;
if ( hollow < 0f )
{
hollow = 0f ;
}
2011-08-25 01:21:51 +00:00
// If the prim is a Cylinder, Prism, Sphere, Torus or Ring (or not a
// Box or Tube) and the hole shape is a square, hollow is limited to
// a max of 70%. The viewer performs its own check on this value but
// we need to do it here also so llGetPrimitiveParams can have access
// to the correct value.
if ( profileshape ! = ( byte ) ProfileCurve . Square & &
holeshape = = ( int ) ScriptBaseClass . PRIM_HOLE_SQUARE )
2008-09-26 02:51:00 +00:00
{
2011-08-25 01:21:51 +00:00
if ( hollow > 0.70f )
{
hollow = 0.70f ;
}
}
// Otherwise, hollow is limited to 95%.
else
{
if ( hollow > 0.95f )
{
hollow = 0.95f ;
}
2008-09-26 02:51:00 +00:00
}
shapeBlock . ProfileHollow = ( ushort ) ( 50000 * hollow ) ;
if ( twist . x < - 1.0f )
{
twist . x = - 1.0f ;
}
if ( twist . x > 1.0f )
{
twist . x = 1.0f ;
}
if ( twist . y < - 1.0f )
{
twist . y = - 1.0f ;
}
if ( twist . y > 1.0f )
{
twist . y = 1.0f ;
}
2011-09-04 17:21:29 +00:00
// A fairly large precision error occurs for some calculations,
// if a float or double is directly cast to a byte or sbyte
// variable, in both .Net and Mono. In .Net, coding
// "(sbyte)(float)(some expression)" corrects the precision
// errors. But this does not work for Mono. This longer coding
// form of creating a tempoary float variable from the
// expression first, then casting that variable to a byte or
// sbyte, works for both .Net and Mono. These types of
// assignments occur in SetPrimtiveBlockShapeParams and
// SetPrimitiveShapeParams in support of llSetPrimitiveParams.
tempFloat = ( float ) ( 100.0d * twist . x ) ;
shapeBlock . PathTwistBegin = ( sbyte ) tempFloat ;
tempFloat = ( float ) ( 100.0d * twist . y ) ;
shapeBlock . PathTwist = ( sbyte ) tempFloat ;
2008-09-26 02:51:00 +00:00
shapeBlock . ObjectLocalID = part . LocalId ;
2009-12-24 19:00:08 +00:00
part . Shape . SculptEntry = false ;
2008-09-26 02:51:00 +00:00
return shapeBlock ;
}
2011-08-25 01:21:51 +00:00
// 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 )
2008-09-26 02:51:00 +00:00
{
2011-09-04 17:21:29 +00:00
float tempFloat ; // Use in float expressions below to avoid byte cast precision issues.
2008-09-26 02:51:00 +00:00
ObjectShapePacket . ObjectDataBlock shapeBlock ;
2011-08-25 01:21:51 +00:00
shapeBlock = SetPrimitiveBlockShapeParams ( part , holeshape , cut , hollow , twist , profileshape , pathcurve ) ;
2008-09-26 02:51:00 +00:00
if ( taper_b . x < 0f )
{
taper_b . x = 0f ;
}
if ( taper_b . x > 2f )
{
taper_b . x = 2f ;
}
if ( taper_b . y < 0f )
{
taper_b . y = 0f ;
}
if ( taper_b . y > 2f )
{
taper_b . y = 2f ;
}
2011-09-04 17:21:29 +00:00
tempFloat = ( float ) ( 100.0d * ( 2.0d - taper_b . x ) ) ;
shapeBlock . PathScaleX = ( byte ) tempFloat ;
tempFloat = ( float ) ( 100.0d * ( 2.0d - taper_b . y ) ) ;
shapeBlock . PathScaleY = ( byte ) tempFloat ;
2008-09-26 02:51:00 +00:00
if ( topshear . x < - 0.5f )
{
topshear . x = - 0.5f ;
}
if ( topshear . x > 0.5f )
{
topshear . x = 0.5f ;
}
if ( topshear . y < - 0.5f )
{
topshear . y = - 0.5f ;
}
if ( topshear . y > 0.5f )
{
topshear . y = 0.5f ;
}
2011-09-04 17:21:29 +00:00
tempFloat = ( float ) ( 100.0d * topshear . x ) ;
shapeBlock . PathShearX = ( byte ) tempFloat ;
tempFloat = ( float ) ( 100.0d * topshear . y ) ;
shapeBlock . PathShearY = ( byte ) tempFloat ;
2008-09-26 02:51:00 +00:00
2009-12-24 19:00:08 +00:00
part . Shape . SculptEntry = false ;
2008-09-26 02:51:00 +00:00
part . UpdateShape ( shapeBlock ) ;
}
2011-08-25 01:21:51 +00:00
// 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 )
2008-09-26 02:51:00 +00:00
{
ObjectShapePacket . ObjectDataBlock shapeBlock ;
2011-08-25 01:21:51 +00:00
shapeBlock = SetPrimitiveBlockShapeParams ( part , holeshape , cut , hollow , twist , profileshape , pathcurve ) ;
2008-09-26 02:51:00 +00:00
// profile/path swapped for a sphere
shapeBlock . PathBegin = shapeBlock . ProfileBegin ;
shapeBlock . PathEnd = shapeBlock . ProfileEnd ;
shapeBlock . PathScaleX = 100 ;
shapeBlock . PathScaleY = 100 ;
if ( dimple . x < 0f )
{
dimple . x = 0f ;
}
if ( dimple . x > 1f )
{
dimple . x = 1f ;
}
if ( dimple . y < 0f )
{
dimple . y = 0f ;
}
if ( dimple . y > 1f )
{
dimple . y = 1f ;
}
if ( dimple . y - cut . x < 0.05f )
{
dimple . x = cut . y - 0.05f ;
}
shapeBlock . ProfileBegin = ( ushort ) ( 50000 * dimple . x ) ;
shapeBlock . ProfileEnd = ( ushort ) ( 50000 * ( 1 - dimple . y ) ) ;
2009-12-24 19:00:08 +00:00
part . Shape . SculptEntry = false ;
2008-09-26 02:51:00 +00:00
part . UpdateShape ( shapeBlock ) ;
}
2011-08-25 01:21:51 +00:00
// 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 )
2008-09-26 02:51:00 +00:00
{
2011-09-04 17:21:29 +00:00
float tempFloat ; // Use in float expressions below to avoid byte cast precision issues.
2008-09-26 02:51:00 +00:00
ObjectShapePacket . ObjectDataBlock shapeBlock ;
2011-08-25 01:21:51 +00:00
shapeBlock = SetPrimitiveBlockShapeParams ( part , holeshape , cut , hollow , twist , profileshape , pathcurve ) ;
2008-09-26 02:51:00 +00:00
// profile/path swapped for a torrus, tube, ring
shapeBlock . PathBegin = shapeBlock . ProfileBegin ;
shapeBlock . PathEnd = shapeBlock . ProfileEnd ;
if ( holesize . x < 0.05f )
{
holesize . x = 0.05f ;
}
if ( holesize . x > 1f )
{
holesize . x = 1f ;
}
if ( holesize . y < 0.05f )
{
holesize . y = 0.05f ;
}
if ( holesize . y > 0.5f )
{
holesize . y = 0.5f ;
}
2011-09-04 17:21:29 +00:00
tempFloat = ( float ) ( 100.0d * ( 2.0d - holesize . x ) ) ;
shapeBlock . PathScaleX = ( byte ) tempFloat ;
tempFloat = ( float ) ( 100.0d * ( 2.0d - holesize . y ) ) ;
shapeBlock . PathScaleY = ( byte ) tempFloat ;
2008-09-26 02:51:00 +00:00
if ( topshear . x < - 0.5f )
{
topshear . x = - 0.5f ;
}
if ( topshear . x > 0.5f )
{
topshear . x = 0.5f ;
}
if ( topshear . y < - 0.5f )
{
topshear . y = - 0.5f ;
}
if ( topshear . y > 0.5f )
{
topshear . y = 0.5f ;
}
2011-09-04 17:21:29 +00:00
tempFloat = ( float ) ( 100.0d * topshear . x ) ;
shapeBlock . PathShearX = ( byte ) tempFloat ;
tempFloat = ( float ) ( 100.0d * topshear . y ) ;
shapeBlock . PathShearY = ( byte ) tempFloat ;
2008-09-26 02:51:00 +00:00
if ( profilecut . x < 0f )
{
profilecut . x = 0f ;
}
if ( profilecut . x > 1f )
{
profilecut . x = 1f ;
}
if ( profilecut . y < 0f )
{
profilecut . y = 0f ;
}
if ( profilecut . y > 1f )
{
profilecut . y = 1f ;
}
2010-06-19 23:07:35 +00:00
if ( profilecut . y - profilecut . x < 0.05f )
2008-09-26 02:51:00 +00:00
{
2010-06-25 12:15:26 +00:00
profilecut . x = profilecut . y - 0.05f ;
if ( profilecut . x < 0.0f )
{
profilecut . x = 0.0f ;
profilecut . y = 0.05f ;
2010-06-19 23:07:35 +00:00
}
2008-09-26 02:51:00 +00:00
}
shapeBlock . ProfileBegin = ( ushort ) ( 50000 * profilecut . x ) ;
shapeBlock . ProfileEnd = ( ushort ) ( 50000 * ( 1 - profilecut . y ) ) ;
if ( taper_a . x < - 1f )
{
taper_a . x = - 1f ;
}
if ( taper_a . x > 1f )
{
taper_a . x = 1f ;
}
if ( taper_a . y < - 1f )
{
taper_a . y = - 1f ;
}
if ( taper_a . y > 1f )
{
taper_a . y = 1f ;
}
2011-09-04 17:21:29 +00:00
tempFloat = ( float ) ( 100.0d * taper_a . x ) ;
shapeBlock . PathTaperX = ( sbyte ) tempFloat ;
tempFloat = ( float ) ( 100.0d * taper_a . y ) ;
shapeBlock . PathTaperY = ( sbyte ) tempFloat ;
2008-09-26 02:51:00 +00:00
if ( revolutions < 1f )
{
revolutions = 1f ;
}
if ( revolutions > 4f )
{
revolutions = 4f ;
}
2011-09-04 17:21:29 +00:00
tempFloat = 66.66667f * ( revolutions - 1.0f ) ;
shapeBlock . PathRevolutions = ( byte ) tempFloat ;
2008-09-26 02:51:00 +00:00
// limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
if ( radiusoffset < 0f )
{
radiusoffset = 0f ;
}
if ( radiusoffset > 1f )
{
radiusoffset = 1f ;
}
2011-09-04 17:21:29 +00:00
tempFloat = 100.0f * radiusoffset ;
shapeBlock . PathRadiusOffset = ( sbyte ) tempFloat ;
2008-09-26 02:51:00 +00:00
if ( skew < - 0.95f )
{
skew = - 0.95f ;
}
if ( skew > 0.95f )
{
skew = 0.95f ;
}
2011-09-04 17:21:29 +00:00
tempFloat = 100.0f * skew ;
shapeBlock . PathSkew = ( sbyte ) tempFloat ;
2008-09-26 02:51:00 +00:00
2009-12-24 19:00:08 +00:00
part . Shape . SculptEntry = false ;
2008-09-26 02:51:00 +00:00
part . UpdateShape ( shapeBlock ) ;
}
2011-08-25 01:21:51 +00:00
// Prim type sculpt.
protected void SetPrimitiveShapeParams ( SceneObjectPart part , string map , int type , byte pathcurve )
2008-09-26 02:51:00 +00:00
{
ObjectShapePacket . ObjectDataBlock shapeBlock = new ObjectShapePacket . ObjectDataBlock ( ) ;
UUID sculptId ;
if ( ! UUID . TryParse ( map , out sculptId ) )
{
2009-04-02 10:24:12 +00:00
sculptId = InventoryKey ( map , ( int ) AssetType . Texture ) ;
2008-09-26 02:51:00 +00:00
}
2009-04-02 10:24:12 +00:00
if ( sculptId = = UUID . Zero )
return ;
2011-08-25 01:21:51 +00:00
shapeBlock . PathCurve = pathcurve ;
2008-09-26 02:51:00 +00:00
shapeBlock . ObjectLocalID = part . LocalId ;
shapeBlock . PathScaleX = 100 ;
shapeBlock . PathScaleY = 150 ;
2012-02-25 15:39:14 +00:00
int flag = type & ( ScriptBaseClass . PRIM_SCULPT_FLAG_INVERT | ScriptBaseClass . PRIM_SCULPT_FLAG_MIRROR ) ;
if ( type ! = ( ScriptBaseClass . PRIM_SCULPT_TYPE_CYLINDER | flag ) & &
type ! = ( ScriptBaseClass . PRIM_SCULPT_TYPE_PLANE | flag ) & &
type ! = ( ScriptBaseClass . PRIM_SCULPT_TYPE_SPHERE | flag ) & &
type ! = ( ScriptBaseClass . PRIM_SCULPT_TYPE_TORUS | flag ) )
2008-09-26 02:51:00 +00:00
{
// default
type = ( int ) ScriptBaseClass . PRIM_SCULPT_TYPE_SPHERE ;
}
2011-07-08 23:42:48 +00:00
part . Shape . SetSculptProperties ( ( byte ) type , sculptId ) ;
2008-09-26 02:51:00 +00:00
part . Shape . SculptEntry = true ;
part . UpdateShape ( shapeBlock ) ;
}
public void llSetPrimitiveParams ( LSL_List rules )
{
2008-11-08 21:25:26 +00:00
m_host . AddScriptLPS ( 1 ) ;
2012-08-15 20:14:39 +00:00
2012-08-28 02:21:04 +00:00
setLinkPrimParams ( ScriptBaseClass . LINK_THIS , rules , "llSetPrimitiveParams" ) ;
2010-09-24 14:26:53 +00:00
ScriptSleep ( 200 ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetLinkPrimitiveParams ( int linknumber , LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-28 02:21:04 +00:00
setLinkPrimParams ( linknumber , rules , "llSetLinkPrimitiveParams" ) ;
2010-09-24 14:26:53 +00:00
ScriptSleep ( 200 ) ;
2008-09-26 02:51:00 +00:00
}
2010-03-06 06:56:55 +00:00
public void llSetLinkPrimitiveParamsFast ( int linknumber , LSL_List rules )
{
2010-10-21 19:16:30 +00:00
m_host . AddScriptLPS ( 1 ) ;
2012-08-28 02:21:04 +00:00
setLinkPrimParams ( linknumber , rules , "llSetLinkPrimitiveParamsFast" ) ;
2011-10-25 12:27:09 +00:00
}
2012-08-28 02:21:04 +00:00
protected void setLinkPrimParams ( int linknumber , LSL_List rules , string originFunc )
2011-10-25 12:27:09 +00:00
{
2010-10-21 19:16:30 +00:00
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
2012-08-15 20:14:39 +00:00
LSL_List remaining = null ;
2012-08-28 02:40:27 +00:00
uint rulesParsed = 0 ;
2012-08-15 20:14:39 +00:00
2010-10-21 19:16:30 +00:00
foreach ( SceneObjectPart part in parts )
2012-08-28 02:40:27 +00:00
remaining = SetPrimParams ( part , rules , originFunc , ref rulesParsed ) ;
2012-08-15 20:14:39 +00:00
2012-08-24 16:44:28 +00:00
while ( remaining ! = null & & remaining . Length > 2 )
2012-08-15 20:14:39 +00:00
{
linknumber = remaining . GetLSLIntegerItem ( 0 ) ;
2012-08-24 16:44:28 +00:00
rules = remaining . GetSublist ( 1 , - 1 ) ;
2012-08-15 20:14:39 +00:00
parts = GetLinkParts ( linknumber ) ;
foreach ( SceneObjectPart part in parts )
2012-08-28 02:40:27 +00:00
remaining = SetPrimParams ( part , rules , originFunc , ref rulesParsed ) ;
2012-08-15 20:14:39 +00:00
}
2010-03-06 06:56:55 +00:00
}
2012-08-28 02:40:27 +00:00
protected LSL_List SetPrimParams ( SceneObjectPart part , LSL_List rules , string originFunc , ref uint rulesParsed )
2008-09-26 02:51:00 +00:00
{
int idx = 0 ;
2012-08-28 02:21:04 +00:00
int idxStart = 0 ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:02:44 +00:00
bool positionChanged = false ;
LSL_Vector currentPosition = GetPartLocalPos ( part ) ;
2011-11-02 12:09:18 +00:00
try
2008-09-26 02:51:00 +00:00
{
2011-11-02 12:09:18 +00:00
while ( idx < rules . Length )
{
2012-08-28 02:40:27 +00:00
+ + rulesParsed ;
2011-11-02 12:09:18 +00:00
int code = rules . GetLSLIntegerItem ( idx + + ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
int remain = rules . Length - idx ;
2012-08-28 02:21:04 +00:00
idxStart = idx ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
int face ;
LSL_Vector v ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
switch ( code )
{
case ( int ) ScriptBaseClass . PRIM_POSITION :
2012-04-06 22:43:03 +00:00
case ( int ) ScriptBaseClass . PRIM_POS_LOCAL :
2011-11-02 12:09:18 +00:00
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
v = rules . GetVector3Item ( idx + + ) ;
positionChanged = true ;
currentPosition = GetSetPosTarget ( part , v , currentPosition ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_SIZE :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
v = rules . GetVector3Item ( idx + + ) ;
SetScale ( part , v ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_ROTATION :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
LSL_Rotation q = rules . GetQuaternionItem ( idx + + ) ;
// try to let this work as in SL...
if ( part . ParentID = = 0 )
{
// special case: If we are root, rotate complete SOG to new rotation
2012-08-18 14:18:31 +00:00
SetRot ( part , q ) ;
2011-11-02 12:09:18 +00:00
}
else
{
// we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
SceneObjectPart rootPart = part . ParentGroup . RootPart ;
2012-08-18 14:18:31 +00:00
SetRot ( part , rootPart . RotationOffset * ( Quaternion ) q ) ;
2011-11-02 12:09:18 +00:00
}
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_TYPE :
if ( remain < 3 )
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
code = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
remain = rules . Length - idx ;
float hollow ;
LSL_Vector twist ;
LSL_Vector taper_b ;
LSL_Vector topshear ;
float revolutions ;
float radiusoffset ;
float skew ;
LSL_Vector holesize ;
LSL_Vector profilecut ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
switch ( code )
{
case ( int ) ScriptBaseClass . PRIM_TYPE_BOX :
if ( remain < 6 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
v = rules . GetVector3Item ( idx + + ) ; // cut
hollow = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
twist = rules . GetVector3Item ( idx + + ) ;
taper_b = rules . GetVector3Item ( idx + + ) ;
topshear = rules . GetVector3Item ( idx + + ) ;
SetPrimitiveShapeParams ( part , face , v , hollow , twist , taper_b , topshear ,
( byte ) ProfileShape . Square , ( byte ) Extrusion . Straight ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TYPE_CYLINDER :
if ( remain < 6 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ; // holeshape
v = rules . GetVector3Item ( idx + + ) ; // cut
hollow = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
twist = rules . GetVector3Item ( idx + + ) ;
taper_b = rules . GetVector3Item ( idx + + ) ;
topshear = rules . GetVector3Item ( idx + + ) ;
SetPrimitiveShapeParams ( part , face , v , hollow , twist , taper_b , topshear ,
( byte ) ProfileShape . Circle , ( byte ) Extrusion . Straight ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TYPE_PRISM :
if ( remain < 6 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ; // holeshape
v = rules . GetVector3Item ( idx + + ) ; //cut
hollow = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
twist = rules . GetVector3Item ( idx + + ) ;
taper_b = rules . GetVector3Item ( idx + + ) ;
topshear = rules . GetVector3Item ( idx + + ) ;
SetPrimitiveShapeParams ( part , face , v , hollow , twist , taper_b , topshear ,
( byte ) ProfileShape . EquilateralTriangle , ( byte ) Extrusion . Straight ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TYPE_SPHERE :
if ( remain < 5 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ; // holeshape
v = rules . GetVector3Item ( idx + + ) ; // cut
hollow = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
twist = rules . GetVector3Item ( idx + + ) ;
taper_b = rules . GetVector3Item ( idx + + ) ; // dimple
SetPrimitiveShapeParams ( part , face , v , hollow , twist , taper_b ,
( byte ) ProfileShape . HalfCircle , ( byte ) Extrusion . Curve1 ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TYPE_TORUS :
if ( remain < 11 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ; // holeshape
v = rules . GetVector3Item ( idx + + ) ; //cut
hollow = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
twist = rules . GetVector3Item ( idx + + ) ;
holesize = rules . GetVector3Item ( idx + + ) ;
topshear = rules . GetVector3Item ( idx + + ) ;
profilecut = rules . GetVector3Item ( idx + + ) ;
taper_b = rules . GetVector3Item ( idx + + ) ; // taper_a
revolutions = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
radiusoffset = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
skew = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
SetPrimitiveShapeParams ( part , face , v , hollow , twist , holesize , topshear , profilecut , taper_b ,
revolutions , radiusoffset , skew , ( byte ) ProfileShape . Circle , ( byte ) Extrusion . Curve1 ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TYPE_TUBE :
if ( remain < 11 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ; // holeshape
v = rules . GetVector3Item ( idx + + ) ; //cut
hollow = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
twist = rules . GetVector3Item ( idx + + ) ;
holesize = rules . GetVector3Item ( idx + + ) ;
topshear = rules . GetVector3Item ( idx + + ) ;
profilecut = rules . GetVector3Item ( idx + + ) ;
taper_b = rules . GetVector3Item ( idx + + ) ; // taper_a
revolutions = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
radiusoffset = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
skew = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
SetPrimitiveShapeParams ( part , face , v , hollow , twist , holesize , topshear , profilecut , taper_b ,
revolutions , radiusoffset , skew , ( byte ) ProfileShape . Square , ( byte ) Extrusion . Curve1 ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TYPE_RING :
if ( remain < 11 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ; // holeshape
v = rules . GetVector3Item ( idx + + ) ; //cut
hollow = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
twist = rules . GetVector3Item ( idx + + ) ;
holesize = rules . GetVector3Item ( idx + + ) ;
topshear = rules . GetVector3Item ( idx + + ) ;
profilecut = rules . GetVector3Item ( idx + + ) ;
taper_b = rules . GetVector3Item ( idx + + ) ; // taper_a
revolutions = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
radiusoffset = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
skew = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
SetPrimitiveShapeParams ( part , face , v , hollow , twist , holesize , topshear , profilecut , taper_b ,
revolutions , radiusoffset , skew , ( byte ) ProfileShape . EquilateralTriangle , ( byte ) Extrusion . Curve1 ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TYPE_SCULPT :
if ( remain < 2 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
string map = rules . Data [ idx + + ] . ToString ( ) ;
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ; // type
SetPrimitiveShapeParams ( part , map , face , ( byte ) Extrusion . Curve1 ) ;
break ;
}
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_TEXTURE :
if ( remain < 5 )
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
string tex = rules . Data [ idx + + ] . ToString ( ) ;
LSL_Vector repeats = rules . GetVector3Item ( idx + + ) ;
LSL_Vector offsets = rules . GetVector3Item ( idx + + ) ;
double rotation = ( double ) rules . GetLSLFloatItem ( idx + + ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
SetTexture ( part , tex , face ) ;
ScaleTexture ( part , repeats . x , repeats . y , face ) ;
OffsetTexture ( part , offsets . x , offsets . y , face ) ;
RotateTexture ( part , rotation , face ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_COLOR :
if ( remain < 3 )
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
LSL_Vector color = rules . GetVector3Item ( idx + + ) ;
double alpha = ( double ) rules . GetLSLFloatItem ( idx + + ) ;
2008-09-26 02:51:00 +00:00
2012-08-20 08:26:26 +00:00
part . SetFaceColorAlpha ( face , color , alpha ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_FLEXIBLE :
if ( remain < 7 )
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
bool flexi = rules . GetLSLIntegerItem ( idx + + ) ;
int softness = rules . GetLSLIntegerItem ( idx + + ) ;
float gravity = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
float friction = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
float wind = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
float tension = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
LSL_Vector force = rules . GetVector3Item ( idx + + ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
SetFlexi ( part , flexi , softness , gravity , friction , wind , tension , force ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_POINT_LIGHT :
if ( remain < 5 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
bool light = rules . GetLSLIntegerItem ( idx + + ) ;
LSL_Vector lightcolor = rules . GetVector3Item ( idx + + ) ;
float intensity = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
float radius = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
float falloff = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
SetPointLight ( part , light , lightcolor , intensity , radius , falloff ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_GLOW :
if ( remain < 2 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = rules . GetLSLIntegerItem ( idx + + ) ;
float glow = ( float ) rules . GetLSLFloatItem ( idx + + ) ;
2010-09-24 14:26:53 +00:00
2011-11-02 12:09:18 +00:00
SetGlow ( part , face , glow ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_BUMP_SHINY :
if ( remain < 3 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
int shiny = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2012-05-03 17:00:09 +00:00
Bumpiness bump = ( Bumpiness ) ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
SetShiny ( part , face , shiny , bump ) ;
2010-09-24 14:26:53 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_FULLBRIGHT :
if ( remain < 2 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
face = rules . GetLSLIntegerItem ( idx + + ) ;
bool st = rules . GetLSLIntegerItem ( idx + + ) ;
SetFullBright ( part , face , st ) ;
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_MATERIAL :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
int mat = rules . GetLSLIntegerItem ( idx + + ) ;
if ( mat < 0 | | mat > 7 )
2012-08-15 20:14:39 +00:00
return null ;
2010-09-24 14:26:53 +00:00
2011-11-02 12:09:18 +00:00
part . Material = Convert . ToByte ( mat ) ;
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_PHANTOM :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
string ph = rules . Data [ idx + + ] . ToString ( ) ;
m_host . ParentGroup . ScriptSetPhantomStatus ( ph . Equals ( "1" ) ) ;
2010-09-24 14:26:53 +00:00
2011-11-02 12:09:18 +00:00
break ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_PHYSICS :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
string phy = rules . Data [ idx + + ] . ToString ( ) ;
bool physics ;
2008-09-26 02:51:00 +00:00
2011-11-02 12:09:18 +00:00
if ( phy . Equals ( "1" ) )
physics = true ;
else
physics = false ;
2010-09-24 14:26:53 +00:00
2011-11-02 12:09:18 +00:00
part . ScriptSetPhysicsStatus ( physics ) ;
break ;
2008-11-08 21:25:26 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_TEMP_ON_REZ :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
string temp = rules . Data [ idx + + ] . ToString ( ) ;
2008-11-08 21:25:26 +00:00
2011-11-02 12:09:18 +00:00
m_host . ParentGroup . ScriptSetTemporaryStatus ( temp . Equals ( "1" ) ) ;
2009-04-27 05:22:44 +00:00
2011-11-02 12:09:18 +00:00
break ;
2009-04-27 05:22:44 +00:00
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_TEXGEN :
if ( remain < 2 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
//face,type
face = rules . GetLSLIntegerItem ( idx + + ) ;
int style = rules . GetLSLIntegerItem ( idx + + ) ;
SetTexGen ( part , face , style ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TEXT :
if ( remain < 3 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
string primText = rules . GetLSLStringItem ( idx + + ) ;
LSL_Vector primTextColor = rules . GetVector3Item ( idx + + ) ;
LSL_Float primTextAlpha = rules . GetLSLFloatItem ( idx + + ) ;
2012-08-18 00:17:01 +00:00
Vector3 av3 = Util . Clip ( primTextColor , 0.0f , 1.0f ) ;
2011-11-02 12:09:18 +00:00
part . SetText ( primText , av3 , Util . Clip ( ( float ) primTextAlpha , 0.0f , 1.0f ) ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_NAME :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
string primName = rules . GetLSLStringItem ( idx + + ) ;
part . Name = primName ;
break ;
case ( int ) ScriptBaseClass . PRIM_DESC :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
string primDesc = rules . GetLSLStringItem ( idx + + ) ;
part . Description = primDesc ;
break ;
case ( int ) ScriptBaseClass . PRIM_ROT_LOCAL :
if ( remain < 1 )
2012-08-15 20:14:39 +00:00
return null ;
2012-08-18 14:18:31 +00:00
SetRot ( part , rules . GetQuaternionItem ( idx + + ) ) ;
2011-11-02 12:09:18 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_OMEGA :
if ( remain < 3 )
2012-08-15 20:14:39 +00:00
return null ;
2011-11-02 12:09:18 +00:00
LSL_Vector axis = rules . GetVector3Item ( idx + + ) ;
LSL_Float spinrate = rules . GetLSLFloatItem ( idx + + ) ;
LSL_Float gain = rules . GetLSLFloatItem ( idx + + ) ;
TargetOmega ( part , axis , ( double ) spinrate , ( double ) gain ) ;
break ;
2012-08-01 14:18:02 +00:00
case ( int ) ScriptBaseClass . PRIM_SLICE :
if ( remain < 1 )
2012-08-16 08:35:27 +00:00
return null ;
2012-08-01 14:18:02 +00:00
LSL_Vector slice = rules . GetVector3Item ( idx + + ) ;
part . UpdateSlice ( ( float ) slice . x , ( float ) slice . y ) ;
break ;
2011-11-02 12:09:18 +00:00
case ( int ) ScriptBaseClass . PRIM_LINK_TARGET :
if ( remain < 3 ) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
2012-08-15 20:14:39 +00:00
return null ;
2010-03-06 06:56:55 +00:00
2012-08-15 20:14:39 +00:00
return rules . GetSublist ( idx , - 1 ) ;
2011-11-02 12:09:18 +00:00
}
2008-09-26 02:51:00 +00:00
}
}
2012-08-16 14:32:20 +00:00
catch ( InvalidCastException e )
{
2012-08-28 02:21:04 +00:00
ShoutError ( string . Format (
"{0} error running rule #{1}: arg #{2} " ,
2012-08-28 02:40:27 +00:00
originFunc , rulesParsed , idx - idxStart ) + e . Message ) ;
2012-08-16 14:32:20 +00:00
}
2011-11-02 12:09:18 +00:00
finally
2011-11-02 12:02:44 +00:00
{
2011-11-02 12:09:18 +00:00
if ( positionChanged )
2011-11-02 12:02:44 +00:00
{
2011-11-02 12:09:18 +00:00
if ( part . ParentGroup . RootPart = = part )
{
SceneObjectGroup parent = part . ParentGroup ;
2012-08-18 00:17:01 +00:00
parent . UpdateGroupPosition ( currentPosition ) ;
2011-11-02 12:09:18 +00:00
}
else
{
2012-08-18 00:17:01 +00:00
part . OffsetPosition = currentPosition ;
2011-11-02 12:09:18 +00:00
SceneObjectGroup parent = part . ParentGroup ;
parent . HasGroupChanged = true ;
parent . ScheduleGroupForTerseUpdate ( ) ;
}
2008-09-26 02:51:00 +00:00
}
}
2012-08-15 20:14:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llStringToBase64 ( string str )
{
m_host . AddScriptLPS ( 1 ) ;
try
{
byte [ ] encData_byte = new byte [ str . Length ] ;
2009-10-03 01:31:08 +00:00
encData_byte = Util . UTF8 . GetBytes ( str ) ;
2008-09-26 02:51:00 +00:00
string encodedData = Convert . ToBase64String ( encData_byte ) ;
return encodedData ;
}
catch ( Exception e )
{
throw new Exception ( "Error in base64Encode" + e . Message ) ;
}
}
public LSL_String llBase64ToString ( string str )
{
m_host . AddScriptLPS ( 1 ) ;
try
{
2009-03-31 05:51:28 +00:00
return Util . Base64ToString ( str ) ;
2008-09-26 02:51:00 +00:00
}
catch ( Exception e )
{
throw new Exception ( "Error in base64Decode" + e . Message ) ;
}
}
2008-09-30 01:59:51 +00:00
public LSL_String llXorBase64Strings ( string str1 , string str2 )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
Deprecated ( "llXorBase64Strings" ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 300 ) ;
2008-09-30 01:59:51 +00:00
return String . Empty ;
2008-09-26 02:51:00 +00:00
}
public void llRemoteDataSetRegion ( )
{
m_host . AddScriptLPS ( 1 ) ;
2010-02-14 21:41:57 +00:00
Deprecated ( "llRemoteDataSetRegion" ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Float llLog10 ( double val )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Log10 ( val ) ;
}
public LSL_Float llLog ( double val )
{
m_host . AddScriptLPS ( 1 ) ;
return ( double ) Math . Log ( val ) ;
}
2009-06-10 04:28:56 +00:00
public LSL_List llGetAnimationList ( string id )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
LSL_List l = new LSL_List ( ) ;
2008-09-26 17:25:22 +00:00
ScenePresence av = World . GetScenePresence ( ( UUID ) id ) ;
Thank you kindly, Idb for a patch that solves:
The following should silently fail when attached,
llBreakAllLinks, llBreakLink, llCreateLink.
The following should be restricted to avatars in the same sim,
llGetAgentInfo, llSameGroup, llGetAgentSize, llGetAnimationList.
Comment added to the following unimplemented functions,
llGetAgentLanguage, llGetAnimation.
2008-10-26 18:26:56 +00:00
if ( av = = null | | av . IsChildAgent ) // only if in the region
2008-09-26 02:51:00 +00:00
return l ;
UUID [ ] anims ;
2009-11-17 15:05:40 +00:00
anims = av . Animator . GetAnimationArray ( ) ;
2008-09-26 02:51:00 +00:00
foreach ( UUID foo in anims )
2011-07-04 13:45:21 +00:00
l . Add ( new LSL_Key ( foo . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
return l ;
}
public void llSetParcelMusicURL ( string url )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
2009-03-06 20:44:31 +00:00
ILandObject land = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) ;
2009-10-15 23:35:27 +00:00
if ( land . LandData . OwnerID ! = m_host . OwnerID )
2008-09-26 02:51:00 +00:00
return ;
2009-07-28 09:40:07 +00:00
2009-03-06 20:44:31 +00:00
land . SetMusicUrl ( url ) ;
2009-07-28 09:40:07 +00:00
2009-10-22 04:42:34 +00:00
ScriptSleep ( 2000 ) ;
2008-09-26 02:51:00 +00:00
}
2012-01-25 20:31:18 +00:00
public LSL_String llGetParcelMusicURL ( )
{
m_host . AddScriptLPS ( 1 ) ;
ILandObject land = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) ;
if ( land . LandData . OwnerID ! = m_host . OwnerID )
return String . Empty ;
return land . GetMusicUrl ( ) ;
}
2008-09-26 02:51:00 +00:00
public LSL_Vector llGetRootPosition ( )
{
m_host . AddScriptLPS ( 1 ) ;
2010-09-24 14:26:53 +00:00
return new LSL_Vector ( m_host . ParentGroup . AbsolutePosition . X , m_host . ParentGroup . AbsolutePosition . Y ,
2009-09-16 14:33:42 +00:00
m_host . ParentGroup . AbsolutePosition . Z ) ;
2008-09-26 02:51:00 +00:00
}
2008-10-27 00:51:50 +00:00
/// <summary>
/// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot
/// http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
/// Also tested in sl in regards to the behaviour in attachments/mouselook
/// In the root prim:-
/// Returns the object rotation if not attached
/// Returns the avatars rotation if attached
/// Returns the camera rotation if attached and the avatar is in mouselook
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_Rotation llGetRootRotation ( )
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-27 00:51:50 +00:00
Quaternion q ;
2011-08-26 23:15:21 +00:00
if ( m_host . ParentGroup . AttachmentPoint ! = 0 )
2008-10-27 00:51:50 +00:00
{
2011-08-26 22:06:41 +00:00
ScenePresence avatar = World . GetScenePresence ( m_host . ParentGroup . AttachedAvatar ) ;
2008-10-27 00:51:50 +00:00
if ( avatar ! = null )
if ( ( avatar . AgentControlFlags & ( uint ) AgentManager . ControlFlags . AGENT_CONTROL_MOUSELOOK ) ! = 0 )
q = avatar . CameraRotation ; // Mouselook
else
q = avatar . Rotation ; // Currently infrequently updated so may be inaccurate
else
2009-10-01 23:45:31 +00:00
q = m_host . ParentGroup . GroupRotation ; // Likely never get here but just in case
2008-10-27 00:51:50 +00:00
}
else
2009-10-01 23:45:31 +00:00
q = m_host . ParentGroup . GroupRotation ; // just the group rotation
2008-10-27 00:51:50 +00:00
return new LSL_Rotation ( q . X , q . Y , q . Z , q . W ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetObjectDesc ( )
{
return m_host . Description ! = null ? m_host . Description : String . Empty ;
}
public void llSetObjectDesc ( string desc )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . Description = desc ! = null ? desc : String . Empty ;
}
public LSL_String llGetCreator ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-10-15 23:35:27 +00:00
return m_host . CreatorID . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetTimestamp ( )
{
m_host . AddScriptLPS ( 1 ) ;
return DateTime . Now . ToUniversalTime ( ) . ToString ( "yyyy-MM-ddTHH:mm:ss.fffffffZ" ) ;
}
public LSL_Integer llGetNumberOfPrims ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-02-13 21:56:50 +00:00
int avatarCount = 0 ;
2011-11-04 00:53:51 +00:00
World . ForEachRootScenePresence ( delegate ( ScenePresence presence )
2009-02-13 21:56:50 +00:00
{
2012-03-31 00:45:37 +00:00
if ( presence . ParentID ! = 0 & & m_host . ParentGroup . ContainsPart ( presence . ParentID ) )
2012-03-09 02:38:11 +00:00
avatarCount + + ;
2010-01-12 01:28:27 +00:00
} ) ;
2009-02-13 21:56:50 +00:00
return m_host . ParentGroup . PrimCount + avatarCount ;
2008-09-26 02:51:00 +00:00
}
2008-10-26 17:09:26 +00:00
/// <summary>
/// A partial implementation.
/// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
/// So far only valid for standing/flying/ground sitting avatars and single prim objects.
/// If the object has multiple prims and/or a sitting avatar then the bounding
/// box is for the root prim only.
/// </summary>
2008-09-26 02:51:00 +00:00
public LSL_List llGetBoundingBox ( string obj )
{
m_host . AddScriptLPS ( 1 ) ;
2008-10-26 17:09:26 +00:00
UUID objID = UUID . Zero ;
LSL_List result = new LSL_List ( ) ;
if ( ! UUID . TryParse ( obj , out objID ) )
{
result . Add ( new LSL_Vector ( ) ) ;
result . Add ( new LSL_Vector ( ) ) ;
return result ;
}
ScenePresence presence = World . GetScenePresence ( objID ) ;
if ( presence ! = null )
{
if ( presence . ParentID = = 0 ) // not sat on an object
{
LSL_Vector lower ;
LSL_Vector upper ;
2010-09-24 14:26:53 +00:00
if ( presence . Animator . Animations . DefaultAnimation . AnimID
2012-03-22 00:10:41 +00:00
= = DefaultAvatarAnimations . AnimsUUID [ "SIT_GROUND_CONSTRAINED" ] )
2008-10-26 17:09:26 +00:00
{
// This is for ground sitting avatars
2008-12-01 00:49:36 +00:00
float height = presence . Appearance . AvatarHeight / 2.66666667f ;
2008-10-26 17:09:26 +00:00
lower = new LSL_Vector ( - 0.3375f , - 0.45f , height * - 1.0f ) ;
upper = new LSL_Vector ( 0.3375f , 0.45f , 0.0f ) ;
}
else
{
// This is for standing/flying avatars
2008-12-01 00:49:36 +00:00
float height = presence . Appearance . AvatarHeight / 2.0f ;
2008-10-26 17:09:26 +00:00
lower = new LSL_Vector ( - 0.225f , - 0.3f , height * - 1.0f ) ;
upper = new LSL_Vector ( 0.225f , 0.3f , height + 0.05f ) ;
}
result . Add ( lower ) ;
result . Add ( upper ) ;
return result ;
}
else
{
// sitting on an object so we need the bounding box of that
// which should include the avatar so set the UUID to the
// UUID of the object the avatar is sat on and allow it to fall through
// to processing an object
SceneObjectPart p = World . GetSceneObjectPart ( presence . ParentID ) ;
objID = p . UUID ;
}
}
SceneObjectPart part = World . GetSceneObjectPart ( objID ) ;
// Currently only works for single prims without a sitting avatar
if ( part ! = null )
{
Vector3 halfSize = part . Scale / 2.0f ;
2012-08-18 00:17:01 +00:00
LSL_Vector lower = ( new LSL_Vector ( halfSize ) ) * - 1.0f ;
LSL_Vector upper = new LSL_Vector ( halfSize ) ;
2008-10-26 17:09:26 +00:00
result . Add ( lower ) ;
result . Add ( upper ) ;
return result ;
}
2009-07-28 09:40:07 +00:00
2008-10-26 17:09:26 +00:00
// Not found so return empty values
result . Add ( new LSL_Vector ( ) ) ;
result . Add ( new LSL_Vector ( ) ) ;
return result ;
2008-09-26 02:51:00 +00:00
}
public LSL_Vector llGetGeometricCenter ( )
{
return new LSL_Vector ( m_host . GetGeometricCenter ( ) . X , m_host . GetGeometricCenter ( ) . Y , m_host . GetGeometricCenter ( ) . Z ) ;
}
public LSL_List llGetPrimitiveParams ( LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
2012-08-24 16:02:13 +00:00
LSL_List result = new LSL_List ( ) ;
2012-08-24 16:44:39 +00:00
LSL_List remaining = GetPrimParams ( m_host , rules , ref result ) ;
while ( remaining ! = null & & remaining . Length > 2 )
{
int linknumber = remaining . GetLSLIntegerItem ( 0 ) ;
rules = remaining . GetSublist ( 1 , - 1 ) ;
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
foreach ( SceneObjectPart part in parts )
remaining = GetPrimParams ( part , rules , ref result ) ;
}
2012-08-24 16:02:13 +00:00
return result ;
2009-08-07 20:51:03 +00:00
}
2010-03-06 06:56:55 +00:00
public LSL_List llGetLinkPrimitiveParams ( int linknumber , LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
LSL_List res = new LSL_List ( ) ;
2012-08-24 16:44:39 +00:00
LSL_List remaining = null ;
2010-03-06 06:56:55 +00:00
2012-08-24 15:41:43 +00:00
foreach ( SceneObjectPart part in parts )
2010-03-06 06:56:55 +00:00
{
2012-08-24 16:44:39 +00:00
remaining = GetPrimParams ( part , rules , ref res ) ;
}
while ( remaining ! = null & & remaining . Length > 2 )
{
linknumber = remaining . GetLSLIntegerItem ( 0 ) ;
rules = remaining . GetSublist ( 1 , - 1 ) ;
parts = GetLinkParts ( linknumber ) ;
foreach ( SceneObjectPart part in parts )
remaining = GetPrimParams ( part , rules , ref res ) ;
2010-03-06 06:56:55 +00:00
}
return res ;
}
2012-08-24 16:44:39 +00:00
public LSL_List GetPrimParams ( SceneObjectPart part , LSL_List rules , ref LSL_List res )
2009-08-07 20:51:03 +00:00
{
2008-09-26 02:51:00 +00:00
int idx = 0 ;
while ( idx < rules . Length )
{
int code = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
int remain = rules . Length - idx ;
switch ( code )
{
case ( int ) ScriptBaseClass . PRIM_MATERIAL :
2009-08-07 20:51:03 +00:00
res . Add ( new LSL_Integer ( part . Material ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_PHYSICS :
2009-08-07 20:51:03 +00:00
if ( ( part . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . Physics ) ! = 0 )
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Integer ( 1 ) ) ;
else
res . Add ( new LSL_Integer ( 0 ) ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_TEMP_ON_REZ :
2009-08-07 20:51:03 +00:00
if ( ( part . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . TemporaryOnRez ) ! = 0 )
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Integer ( 1 ) ) ;
else
res . Add ( new LSL_Integer ( 0 ) ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_PHANTOM :
2009-08-07 20:51:03 +00:00
if ( ( part . GetEffectiveObjectFlags ( ) & ( uint ) PrimFlags . Phantom ) ! = 0 )
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Integer ( 1 ) ) ;
else
res . Add ( new LSL_Integer ( 0 ) ) ;
break ;
case ( int ) ScriptBaseClass . PRIM_POSITION :
2009-12-19 23:25:45 +00:00
LSL_Vector v = new LSL_Vector ( part . AbsolutePosition . X ,
2009-08-07 20:51:03 +00:00
part . AbsolutePosition . Y ,
2009-12-19 23:25:45 +00:00
part . AbsolutePosition . Z ) ;
// For some reason, the part.AbsolutePosition.* values do not change if the
// linkset is rotated; they always reflect the child prim's world position
// as though the linkset is unrotated. This is incompatible behavior with SL's
// implementation, so will break scripts imported from there (not to mention it
// makes it more difficult to determine a child prim's actual inworld position).
if ( part . ParentID ! = 0 )
v = ( ( v - llGetRootPosition ( ) ) * llGetRootRotation ( ) ) + llGetRootPosition ( ) ;
2010-01-03 21:10:45 +00:00
res . Add ( v ) ;
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_SIZE :
2009-08-07 20:51:03 +00:00
res . Add ( new LSL_Vector ( part . Scale . X ,
part . Scale . Y ,
part . Scale . Z ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_ROTATION :
2009-08-18 04:41:38 +00:00
res . Add ( GetPartRot ( part ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_TYPE :
// implementing box
2009-08-07 20:51:03 +00:00
PrimitiveBaseShape Shape = part . Shape ;
2010-02-01 22:33:15 +00:00
int primType = ( int ) part . GetPrimType ( ) ;
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Integer ( primType ) ) ;
2009-12-19 23:25:45 +00:00
double topshearx = ( double ) ( sbyte ) Shape . PathShearX / 100.0 ; // Fix negative values for PathShearX
double topsheary = ( double ) ( sbyte ) Shape . PathShearY / 100.0 ; // and PathShearY.
2008-09-26 02:51:00 +00:00
switch ( primType )
{
case ScriptBaseClass . PRIM_TYPE_BOX :
case ScriptBaseClass . PRIM_TYPE_CYLINDER :
case ScriptBaseClass . PRIM_TYPE_PRISM :
2011-08-13 02:09:01 +00:00
res . Add ( new LSL_Integer ( Shape . ProfileCurve ) & 0xf0 ) ; // Isolate hole shape nibble.
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Vector ( Shape . ProfileBegin / 50000.0 , 1 - Shape . ProfileEnd / 50000.0 , 0 ) ) ;
res . Add ( new LSL_Float ( Shape . ProfileHollow / 50000.0 ) ) ;
res . Add ( new LSL_Vector ( Shape . PathTwistBegin / 100.0 , Shape . PathTwist / 100.0 , 0 ) ) ;
res . Add ( new LSL_Vector ( 1 - ( Shape . PathScaleX / 100.0 - 1 ) , 1 - ( Shape . PathScaleY / 100.0 - 1 ) , 0 ) ) ;
2009-12-19 23:25:45 +00:00
res . Add ( new LSL_Vector ( topshearx , topsheary , 0 ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case ScriptBaseClass . PRIM_TYPE_SPHERE :
2011-08-13 02:09:01 +00:00
res . Add ( new LSL_Integer ( Shape . ProfileCurve ) & 0xf0 ) ; // Isolate hole shape nibble.
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Vector ( Shape . PathBegin / 50000.0 , 1 - Shape . PathEnd / 50000.0 , 0 ) ) ;
res . Add ( new LSL_Float ( Shape . ProfileHollow / 50000.0 ) ) ;
res . Add ( new LSL_Vector ( Shape . PathTwistBegin / 100.0 , Shape . PathTwist / 100.0 , 0 ) ) ;
res . Add ( new LSL_Vector ( Shape . ProfileBegin / 50000.0 , 1 - Shape . ProfileEnd / 50000.0 , 0 ) ) ;
break ;
case ScriptBaseClass . PRIM_TYPE_SCULPT :
res . Add ( Shape . SculptTexture . ToString ( ) ) ;
res . Add ( new LSL_Integer ( Shape . SculptType ) ) ;
break ;
case ScriptBaseClass . PRIM_TYPE_RING :
case ScriptBaseClass . PRIM_TYPE_TUBE :
case ScriptBaseClass . PRIM_TYPE_TORUS :
// holeshape
2011-08-13 02:09:01 +00:00
res . Add ( new LSL_Integer ( Shape . ProfileCurve ) & 0xf0 ) ; // Isolate hole shape nibble.
2008-09-26 02:51:00 +00:00
// cut
res . Add ( new LSL_Vector ( Shape . PathBegin / 50000.0 , 1 - Shape . PathEnd / 50000.0 , 0 ) ) ;
// hollow
res . Add ( new LSL_Float ( Shape . ProfileHollow / 50000.0 ) ) ;
// twist
res . Add ( new LSL_Vector ( Shape . PathTwistBegin / 100.0 , Shape . PathTwist / 100.0 , 0 ) ) ;
// vector holesize
res . Add ( new LSL_Vector ( 1 - ( Shape . PathScaleX / 100.0 - 1 ) , 1 - ( Shape . PathScaleY / 100.0 - 1 ) , 0 ) ) ;
// vector topshear
2009-12-19 23:25:45 +00:00
res . Add ( new LSL_Vector ( topshearx , topsheary , 0 ) ) ;
2008-09-26 02:51:00 +00:00
// vector profilecut
res . Add ( new LSL_Vector ( Shape . ProfileBegin / 50000.0 , 1 - Shape . ProfileEnd / 50000.0 , 0 ) ) ;
// vector tapera
res . Add ( new LSL_Vector ( Shape . PathTaperX / 100.0 , Shape . PathTaperY / 100.0 , 0 ) ) ;
2009-07-28 09:40:07 +00:00
// float revolutions
2011-09-04 17:21:29 +00:00
res . Add ( new LSL_Float ( Math . Round ( Shape . PathRevolutions * 0.015d , 2 , MidpointRounding . AwayFromZero ) ) + 1.0d ) ;
// Slightly inaccurate, because an unsigned byte is being used to represent
// the entire range of floating-point values from 1.0 through 4.0 (which is how
// SL does it).
/ /
// Using these formulas to store and retrieve PathRevolutions, it is not
// possible to use all values between 1.00 and 4.00. For instance, you can't
// represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
// use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
// with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
// behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
// In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
// such as 1.10. So, SL must store and retreive the actual user input rather
// than only storing the encoded value.
2010-09-24 14:26:53 +00:00
2009-07-28 09:40:07 +00:00
// float radiusoffset
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Float ( Shape . PathRadiusOffset / 100.0 ) ) ;
// float skew
res . Add ( new LSL_Float ( Shape . PathSkew / 100.0 ) ) ;
break ;
}
break ;
case ( int ) ScriptBaseClass . PRIM_TEXTURE :
if ( remain < 1 )
2012-08-24 16:44:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
int face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2009-08-07 20:51:03 +00:00
Primitive . TextureEntry tex = part . Shape . Textures ;
2008-09-26 02:51:00 +00:00
if ( face = = ScriptBaseClass . ALL_SIDES )
{
2010-02-01 22:29:21 +00:00
for ( face = 0 ; face < GetNumberOfSides ( part ) ; face + + )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntryFace texface = tex . GetFace ( ( uint ) face ) ;
res . Add ( new LSL_String ( texface . TextureID . ToString ( ) ) ) ;
res . Add ( new LSL_Vector ( texface . RepeatU ,
2009-04-27 05:22:44 +00:00
texface . RepeatV ,
0 ) ) ;
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Vector ( texface . OffsetU ,
2009-04-27 05:22:44 +00:00
texface . OffsetV ,
0 ) ) ;
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Float ( texface . Rotation ) ) ;
}
}
else
{
2009-08-07 20:51:03 +00:00
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
2008-09-26 02:51:00 +00:00
{
Primitive . TextureEntryFace texface = tex . GetFace ( ( uint ) face ) ;
res . Add ( new LSL_String ( texface . TextureID . ToString ( ) ) ) ;
res . Add ( new LSL_Vector ( texface . RepeatU ,
2009-04-27 05:22:44 +00:00
texface . RepeatV ,
0 ) ) ;
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Vector ( texface . OffsetU ,
2009-04-27 05:22:44 +00:00
texface . OffsetV ,
0 ) ) ;
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Float ( texface . Rotation ) ) ;
}
}
break ;
case ( int ) ScriptBaseClass . PRIM_COLOR :
if ( remain < 1 )
2012-08-24 16:44:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2009-08-07 20:51:03 +00:00
tex = part . Shape . Textures ;
2008-09-26 02:51:00 +00:00
Color4 texcolor ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
2010-02-01 22:29:21 +00:00
for ( face = 0 ; face < GetNumberOfSides ( part ) ; face + + )
2008-09-26 02:51:00 +00:00
{
texcolor = tex . GetFace ( ( uint ) face ) . RGBA ;
res . Add ( new LSL_Vector ( texcolor . R ,
2009-04-27 05:22:44 +00:00
texcolor . G ,
texcolor . B ) ) ;
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Float ( texcolor . A ) ) ;
}
}
else
{
texcolor = tex . GetFace ( ( uint ) face ) . RGBA ;
res . Add ( new LSL_Vector ( texcolor . R ,
2009-04-27 05:22:44 +00:00
texcolor . G ,
texcolor . B ) ) ;
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Float ( texcolor . A ) ) ;
}
break ;
case ( int ) ScriptBaseClass . PRIM_BUMP_SHINY :
if ( remain < 1 )
2012-08-24 16:44:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2010-11-27 09:59:14 +00:00
tex = part . Shape . Textures ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( face = 0 ; face < GetNumberOfSides ( part ) ; face + + )
{
Primitive . TextureEntryFace texface = tex . GetFace ( ( uint ) face ) ;
// Convert Shininess to PRIM_SHINY_*
res . Add ( new LSL_Integer ( ( uint ) texface . Shiny > > 6 ) ) ;
// PRIM_BUMP_*
res . Add ( new LSL_Integer ( ( int ) texface . Bump ) ) ;
}
}
else
{
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
Primitive . TextureEntryFace texface = tex . GetFace ( ( uint ) face ) ;
// Convert Shininess to PRIM_SHINY_*
res . Add ( new LSL_Integer ( ( uint ) texface . Shiny > > 6 ) ) ;
// PRIM_BUMP_*
res . Add ( new LSL_Integer ( ( int ) texface . Bump ) ) ;
}
}
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_FULLBRIGHT :
if ( remain < 1 )
2012-08-24 16:44:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2010-11-27 09:59:14 +00:00
tex = part . Shape . Textures ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( face = 0 ; face < GetNumberOfSides ( part ) ; face + + )
{
Primitive . TextureEntryFace texface = tex . GetFace ( ( uint ) face ) ;
res . Add ( new LSL_Integer ( texface . Fullbright ? 1 : 0 ) ) ;
}
}
else
{
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
Primitive . TextureEntryFace texface = tex . GetFace ( ( uint ) face ) ;
res . Add ( new LSL_Integer ( texface . Fullbright ? 1 : 0 ) ) ;
}
}
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_FLEXIBLE :
2009-08-07 20:51:03 +00:00
PrimitiveBaseShape shape = part . Shape ;
2008-09-26 02:51:00 +00:00
if ( shape . FlexiEntry )
res . Add ( new LSL_Integer ( 1 ) ) ; // active
else
res . Add ( new LSL_Integer ( 0 ) ) ;
res . Add ( new LSL_Integer ( shape . FlexiSoftness ) ) ; // softness
res . Add ( new LSL_Float ( shape . FlexiGravity ) ) ; // gravity
res . Add ( new LSL_Float ( shape . FlexiDrag ) ) ; // friction
res . Add ( new LSL_Float ( shape . FlexiWind ) ) ; // wind
res . Add ( new LSL_Float ( shape . FlexiTension ) ) ; // tension
res . Add ( new LSL_Vector ( shape . FlexiForceX , // force
2009-04-27 05:22:44 +00:00
shape . FlexiForceY ,
shape . FlexiForceZ ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_TEXGEN :
if ( remain < 1 )
2012-08-24 16:44:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2010-11-27 09:59:14 +00:00
tex = part . Shape . Textures ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( face = 0 ; face < GetNumberOfSides ( part ) ; face + + )
{
MappingType texgen = tex . GetFace ( ( uint ) face ) . TexMapType ;
// Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc.
res . Add ( new LSL_Integer ( ( uint ) texgen > > 1 ) ) ;
}
}
else
{
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
MappingType texgen = tex . GetFace ( ( uint ) face ) . TexMapType ;
res . Add ( new LSL_Integer ( ( uint ) texgen > > 1 ) ) ;
}
}
2008-09-26 02:51:00 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_POINT_LIGHT :
2009-08-07 20:51:03 +00:00
shape = part . Shape ;
2008-09-26 02:51:00 +00:00
if ( shape . LightEntry )
res . Add ( new LSL_Integer ( 1 ) ) ; // active
else
res . Add ( new LSL_Integer ( 0 ) ) ;
res . Add ( new LSL_Vector ( shape . LightColorR , // color
2009-04-27 05:22:44 +00:00
shape . LightColorG ,
shape . LightColorB ) ) ;
2008-09-26 02:51:00 +00:00
res . Add ( new LSL_Float ( shape . LightIntensity ) ) ; // intensity
res . Add ( new LSL_Float ( shape . LightRadius ) ) ; // radius
res . Add ( new LSL_Float ( shape . LightFalloff ) ) ; // falloff
break ;
case ( int ) ScriptBaseClass . PRIM_GLOW :
if ( remain < 1 )
2012-08-24 16:44:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
face = ( int ) rules . GetLSLIntegerItem ( idx + + ) ;
2010-11-27 09:59:14 +00:00
tex = part . Shape . Textures ;
if ( face = = ScriptBaseClass . ALL_SIDES )
{
for ( face = 0 ; face < GetNumberOfSides ( part ) ; face + + )
{
Primitive . TextureEntryFace texface = tex . GetFace ( ( uint ) face ) ;
res . Add ( new LSL_Float ( texface . Glow ) ) ;
}
}
else
{
if ( face > = 0 & & face < GetNumberOfSides ( part ) )
{
Primitive . TextureEntryFace texface = tex . GetFace ( ( uint ) face ) ;
res . Add ( new LSL_Float ( texface . Glow ) ) ;
}
}
2008-09-26 02:51:00 +00:00
break ;
2010-11-27 09:59:14 +00:00
2010-03-06 06:56:55 +00:00
case ( int ) ScriptBaseClass . PRIM_TEXT :
Color4 textColor = part . GetTextColor ( ) ;
2011-07-04 13:45:21 +00:00
res . Add ( new LSL_String ( part . Text ) ) ;
2010-03-06 06:56:55 +00:00
res . Add ( new LSL_Vector ( textColor . R ,
textColor . G ,
textColor . B ) ) ;
res . Add ( new LSL_Float ( textColor . A ) ) ;
break ;
2010-10-24 16:19:48 +00:00
case ( int ) ScriptBaseClass . PRIM_NAME :
2011-07-04 13:45:21 +00:00
res . Add ( new LSL_String ( part . Name ) ) ;
2010-10-24 16:19:48 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_DESC :
2011-07-04 13:45:21 +00:00
res . Add ( new LSL_String ( part . Description ) ) ;
2010-10-24 16:19:48 +00:00
break ;
case ( int ) ScriptBaseClass . PRIM_ROT_LOCAL :
res . Add ( new LSL_Rotation ( part . RotationOffset . X , part . RotationOffset . Y , part . RotationOffset . Z , part . RotationOffset . W ) ) ;
break ;
2011-11-26 22:06:28 +00:00
case ( int ) ScriptBaseClass . PRIM_POS_LOCAL :
res . Add ( new LSL_Vector ( GetPartLocalPos ( part ) ) ) ;
break ;
2012-08-01 14:18:02 +00:00
case ( int ) ScriptBaseClass . PRIM_SLICE :
2012-08-02 08:28:32 +00:00
PrimType prim_type = part . GetPrimType ( ) ;
bool useProfileBeginEnd = ( prim_type = = PrimType . SPHERE | | prim_type = = PrimType . TORUS | | prim_type = = PrimType . TUBE | | prim_type = = PrimType . RING ) ;
2012-08-01 14:18:02 +00:00
res . Add ( new LSL_Vector (
2012-08-02 08:28:32 +00:00
( useProfileBeginEnd ? part . Shape . ProfileBegin : part . Shape . PathBegin ) / 50000.0 ,
1 - ( useProfileBeginEnd ? part . Shape . ProfileEnd : part . Shape . PathEnd ) / 50000.0 ,
2012-08-01 14:18:02 +00:00
0
) ) ;
break ;
2012-08-24 16:44:39 +00:00
case ( int ) ScriptBaseClass . PRIM_LINK_TARGET :
if ( remain < 3 )
return null ;
return rules . GetSublist ( idx , - 1 ) ;
2008-09-26 02:51:00 +00:00
}
}
2012-08-24 16:44:39 +00:00
return null ;
2008-09-26 02:51:00 +00:00
}
2010-07-12 14:47:56 +00:00
public LSL_List llGetPrimMediaParams ( int face , LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
ScriptSleep ( 1000 ) ;
2012-02-24 19:46:14 +00:00
return GetPrimMediaParams ( m_host , face , rules ) ;
}
public LSL_List llGetLinkMedia ( LSL_Integer link , LSL_Integer face , LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
ScriptSleep ( 1000 ) ;
if ( link = = ScriptBaseClass . LINK_ROOT )
return GetPrimMediaParams ( m_host . ParentGroup . RootPart , face , rules ) ;
else if ( link = = ScriptBaseClass . LINK_THIS )
return GetPrimMediaParams ( m_host , face , rules ) ;
else
{
SceneObjectPart part = m_host . ParentGroup . GetLinkNumPart ( link ) ;
if ( null ! = part )
return GetPrimMediaParams ( part , face , rules ) ;
}
return new LSL_List ( ) ;
}
2010-07-12 14:47:56 +00:00
2012-02-24 19:46:14 +00:00
private LSL_List GetPrimMediaParams ( SceneObjectPart part , int face , LSL_List rules )
{
2010-07-12 14:47:56 +00:00
// LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
// TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
// Assuming silently fail means give back an empty list. Ideally, need to check this.
2012-02-24 19:46:14 +00:00
if ( face < 0 | | face > part . GetNumberOfSides ( ) - 1 )
2010-07-12 14:47:56 +00:00
return new LSL_List ( ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
IMoapModule module = m_ScriptEngine . World . RequestModuleInterface < IMoapModule > ( ) ;
if ( null = = module )
2012-02-24 19:46:14 +00:00
return new LSL_List ( ) ;
2010-09-24 14:26:53 +00:00
2012-02-24 19:46:14 +00:00
MediaEntry me = module . GetMediaEntry ( part , face ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
// As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
if ( null = = me )
return new LSL_List ( ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
LSL_List res = new LSL_List ( ) ;
for ( int i = 0 ; i < rules . Length ; i + + )
{
int code = ( int ) rules . GetLSLIntegerItem ( i ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
switch ( code )
{
case ScriptBaseClass . PRIM_MEDIA_ALT_IMAGE_ENABLE :
// Not implemented
res . Add ( new LSL_Integer ( 0 ) ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_CONTROLS :
if ( me . Controls = = MediaControls . Standard )
res . Add ( new LSL_Integer ( ScriptBaseClass . PRIM_MEDIA_CONTROLS_STANDARD ) ) ;
else
res . Add ( new LSL_Integer ( ScriptBaseClass . PRIM_MEDIA_CONTROLS_MINI ) ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_CURRENT_URL :
res . Add ( new LSL_String ( me . CurrentURL ) ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_HOME_URL :
res . Add ( new LSL_String ( me . HomeURL ) ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_AUTO_LOOP :
res . Add ( me . AutoLoop ? ScriptBaseClass . TRUE : ScriptBaseClass . FALSE ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_AUTO_PLAY :
res . Add ( me . AutoPlay ? ScriptBaseClass . TRUE : ScriptBaseClass . FALSE ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_AUTO_SCALE :
res . Add ( me . AutoScale ? ScriptBaseClass . TRUE : ScriptBaseClass . FALSE ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_AUTO_ZOOM :
res . Add ( me . AutoZoom ? ScriptBaseClass . TRUE : ScriptBaseClass . FALSE ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_FIRST_CLICK_INTERACT :
res . Add ( me . InteractOnFirstClick ? ScriptBaseClass . TRUE : ScriptBaseClass . FALSE ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_WIDTH_PIXELS :
res . Add ( new LSL_Integer ( me . Width ) ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_HEIGHT_PIXELS :
res . Add ( new LSL_Integer ( me . Height ) ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_WHITELIST_ENABLE :
res . Add ( me . EnableWhiteList ? ScriptBaseClass . TRUE : ScriptBaseClass . FALSE ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_WHITELIST :
string [ ] urls = ( string [ ] ) me . WhiteList . Clone ( ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
for ( int j = 0 ; j < urls . Length ; j + + )
urls [ j ] = Uri . EscapeDataString ( urls [ j ] ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
res . Add ( new LSL_String ( string . Join ( ", " , urls ) ) ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_PERMS_INTERACT :
res . Add ( new LSL_Integer ( ( int ) me . InteractPermissions ) ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
case ScriptBaseClass . PRIM_MEDIA_PERMS_CONTROL :
res . Add ( new LSL_Integer ( ( int ) me . ControlPermissions ) ) ;
break ;
2012-02-24 19:46:14 +00:00
default : return ScriptBaseClass . LSL_STATUS_MALFORMED_PARAMS ;
2010-07-12 14:47:56 +00:00
}
2010-09-12 17:43:49 +00:00
}
2010-09-24 14:26:53 +00:00
2010-07-12 14:47:56 +00:00
return res ;
}
2010-09-24 14:26:53 +00:00
2012-02-24 19:46:14 +00:00
public LSL_Integer llSetPrimMediaParams ( LSL_Integer face , LSL_List rules )
2010-07-12 18:46:23 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
ScriptSleep ( 1000 ) ;
2012-02-24 19:46:14 +00:00
return SetPrimMediaParams ( m_host , face , rules ) ;
}
2010-07-12 18:46:23 +00:00
2012-02-24 19:46:14 +00:00
public LSL_Integer llSetLinkMedia ( LSL_Integer link , LSL_Integer face , LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
ScriptSleep ( 1000 ) ;
if ( link = = ScriptBaseClass . LINK_ROOT )
return SetPrimMediaParams ( m_host . ParentGroup . RootPart , face , rules ) ;
else if ( link = = ScriptBaseClass . LINK_THIS )
return SetPrimMediaParams ( m_host , face , rules ) ;
else
{
SceneObjectPart part = m_host . ParentGroup . GetLinkNumPart ( link ) ;
if ( null ! = part )
return SetPrimMediaParams ( part , face , rules ) ;
}
2010-09-24 14:26:53 +00:00
2012-02-24 19:46:14 +00:00
return ScriptBaseClass . LSL_STATUS_NOT_FOUND ;
2010-07-12 18:46:23 +00:00
}
2010-09-24 14:26:53 +00:00
2012-02-24 19:46:14 +00:00
private LSL_Integer SetPrimMediaParams ( SceneObjectPart part , LSL_Integer face , LSL_List rules )
2010-07-12 18:46:23 +00:00
{
2012-02-24 19:46:14 +00:00
// LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
// Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
// Don't perform the media check directly
if ( face < 0 | | face > part . GetNumberOfSides ( ) - 1 )
return ScriptBaseClass . LSL_STATUS_NOT_FOUND ;
2010-07-12 18:46:23 +00:00
IMoapModule module = m_ScriptEngine . World . RequestModuleInterface < IMoapModule > ( ) ;
if ( null = = module )
2012-02-24 19:46:14 +00:00
return ScriptBaseClass . LSL_STATUS_NOT_SUPPORTED ;
2010-09-24 14:26:53 +00:00
2012-02-24 19:46:14 +00:00
MediaEntry me = module . GetMediaEntry ( part , face ) ;
2010-07-12 18:46:23 +00:00
if ( null = = me )
me = new MediaEntry ( ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
int i = 0 ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
while ( i < rules . Length - 1 )
{
int code = rules . GetLSLIntegerItem ( i + + ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
switch ( code )
{
case ScriptBaseClass . PRIM_MEDIA_ALT_IMAGE_ENABLE :
me . EnableAlterntiveImage = ( rules . GetLSLIntegerItem ( i + + ) ! = 0 ? true : false ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_CONTROLS :
int v = rules . GetLSLIntegerItem ( i + + ) ;
if ( ScriptBaseClass . PRIM_MEDIA_CONTROLS_STANDARD = = v )
me . Controls = MediaControls . Standard ;
else
me . Controls = MediaControls . Mini ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_CURRENT_URL :
me . CurrentURL = rules . GetLSLStringItem ( i + + ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_HOME_URL :
me . HomeURL = rules . GetLSLStringItem ( i + + ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_AUTO_LOOP :
me . AutoLoop = ( ScriptBaseClass . TRUE = = rules . GetLSLIntegerItem ( i + + ) ? true : false ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_AUTO_PLAY :
me . AutoPlay = ( ScriptBaseClass . TRUE = = rules . GetLSLIntegerItem ( i + + ) ? true : false ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_AUTO_SCALE :
me . AutoScale = ( ScriptBaseClass . TRUE = = rules . GetLSLIntegerItem ( i + + ) ? true : false ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_AUTO_ZOOM :
me . AutoZoom = ( ScriptBaseClass . TRUE = = rules . GetLSLIntegerItem ( i + + ) ? true : false ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_FIRST_CLICK_INTERACT :
me . InteractOnFirstClick = ( ScriptBaseClass . TRUE = = rules . GetLSLIntegerItem ( i + + ) ? true : false ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_WIDTH_PIXELS :
me . Width = ( int ) rules . GetLSLIntegerItem ( i + + ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_HEIGHT_PIXELS :
me . Height = ( int ) rules . GetLSLIntegerItem ( i + + ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_WHITELIST_ENABLE :
me . EnableWhiteList = ( ScriptBaseClass . TRUE = = rules . GetLSLIntegerItem ( i + + ) ? true : false ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_WHITELIST :
string [ ] rawWhiteListUrls = rules . GetLSLStringItem ( i + + ) . ToString ( ) . Split ( new char [ ] { ',' } ) ;
List < string > whiteListUrls = new List < string > ( ) ;
Array . ForEach (
rawWhiteListUrls , delegate ( string rawUrl ) { whiteListUrls . Add ( rawUrl . Trim ( ) ) ; } ) ;
me . WhiteList = whiteListUrls . ToArray ( ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_PERMS_INTERACT :
me . InteractPermissions = ( MediaPermission ) ( byte ) ( int ) rules . GetLSLIntegerItem ( i + + ) ;
break ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
case ScriptBaseClass . PRIM_MEDIA_PERMS_CONTROL :
me . ControlPermissions = ( MediaPermission ) ( byte ) ( int ) rules . GetLSLIntegerItem ( i + + ) ;
break ;
2012-02-24 19:46:14 +00:00
default : return ScriptBaseClass . LSL_STATUS_MALFORMED_PARAMS ;
2010-07-12 18:46:23 +00:00
}
2010-09-12 17:43:49 +00:00
}
2010-09-24 14:26:53 +00:00
2012-02-24 19:46:14 +00:00
module . SetMediaEntry ( part , face , me ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 18:46:23 +00:00
return ScriptBaseClass . LSL_STATUS_OK ;
}
2010-09-24 14:26:53 +00:00
2010-07-12 21:00:45 +00:00
public LSL_Integer llClearPrimMedia ( LSL_Integer face )
{
m_host . AddScriptLPS ( 1 ) ;
ScriptSleep ( 1000 ) ;
2012-02-24 19:46:14 +00:00
return ClearPrimMedia ( m_host , face ) ;
}
2010-07-12 21:00:45 +00:00
2012-02-24 19:46:14 +00:00
public LSL_Integer llClearLinkMedia ( LSL_Integer link , LSL_Integer face )
{
m_host . AddScriptLPS ( 1 ) ;
ScriptSleep ( 1000 ) ;
if ( link = = ScriptBaseClass . LINK_ROOT )
return ClearPrimMedia ( m_host . ParentGroup . RootPart , face ) ;
else if ( link = = ScriptBaseClass . LINK_THIS )
return ClearPrimMedia ( m_host , face ) ;
else
{
SceneObjectPart part = m_host . ParentGroup . GetLinkNumPart ( link ) ;
if ( null ! = part )
return ClearPrimMedia ( part , face ) ;
}
return ScriptBaseClass . LSL_STATUS_NOT_FOUND ;
}
private LSL_Integer ClearPrimMedia ( SceneObjectPart part , LSL_Integer face )
{
2010-07-12 21:00:45 +00:00
// LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid
// Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
// FIXME: Don't perform the media check directly
2012-02-24 19:46:14 +00:00
if ( face < 0 | | face > part . GetNumberOfSides ( ) - 1 )
return ScriptBaseClass . LSL_STATUS_NOT_FOUND ;
2010-09-24 14:26:53 +00:00
2010-07-12 21:00:45 +00:00
IMoapModule module = m_ScriptEngine . World . RequestModuleInterface < IMoapModule > ( ) ;
if ( null = = module )
2012-02-24 19:46:14 +00:00
return ScriptBaseClass . LSL_STATUS_NOT_SUPPORTED ;
2010-09-24 14:26:53 +00:00
2012-02-24 19:46:14 +00:00
module . ClearMediaEntry ( part , face ) ;
2010-09-24 14:26:53 +00:00
2010-07-12 21:00:45 +00:00
return ScriptBaseClass . LSL_STATUS_OK ;
}
2010-09-24 14:26:53 +00:00
2008-09-26 02:51:00 +00:00
// <remarks>
// <para>
// The .NET definition of base 64 is:
// <list>
// <item>
// Significant: A-Z a-z 0-9 + -
// </item>
// <item>
// Whitespace: \t \n \r ' '
// </item>
// <item>
// Valueless: =
// </item>
// <item>
// End-of-string: \0 or '=='
// </item>
// </list>
// </para>
// <para>
// Each point in a base-64 string represents
// a 6 bit value. A 32-bit integer can be
// represented using 6 characters (with some
// redundancy).
// </para>
// <para>
// LSL requires a base64 string to be 8
// characters in length. LSL also uses '/'
// rather than '-' (MIME compliant).
// </para>
// <para>
// RFC 1341 used as a reference (as specified
// by the SecondLife Wiki).
// </para>
// <para>
// SL do not record any kind of exception for
// these functions, so the string to integer
// conversion returns '0' if an invalid
// character is encountered during conversion.
// </para>
// <para>
// References
// <list>
// <item>
// http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
// </item>
// <item>
// </item>
// </list>
// </para>
// </remarks>
// <summary>
// Table for converting 6-bit integers into
// base-64 characters
// </summary>
2009-07-06 13:09:03 +00:00
protected static readonly char [ ] i2ctable =
2008-09-26 02:51:00 +00:00
{
'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' ,
'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' ,
'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' ,
'Y' , 'Z' ,
'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' ,
'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' ,
'y' , 'z' ,
'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
'8' , '9' ,
'+' , '/'
} ;
// <summary>
// Table for converting base-64 characters
// into 6-bit integers.
// </summary>
2009-07-06 13:09:03 +00:00
protected static readonly int [ ] c2itable =
2008-09-26 02:51:00 +00:00
{
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // 0x
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // 1x
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // 2x
- 1 , - 1 , - 1 , 63 , - 1 , - 1 , - 1 , 64 ,
53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , // 3x
61 , 62 , - 1 , - 1 , - 1 , 0 , - 1 , - 1 ,
- 1 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , // 4x
8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ,
16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , // 5x
24 , 25 , 26 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , // 6x
34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 ,
42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , // 7x
50 , 51 , 52 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // 8x
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // 9x
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // Ax
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // Bx
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // Cx
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // Dx
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // Ex
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , // Fx
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1
} ;
// <summary>
// Converts a 32-bit integer into a Base64
// character string. Base64 character strings
// are always 8 characters long. All iinteger
// values are acceptable.
// </summary>
// <param name="number">
// 32-bit integer to be converted.
// </param>
// <returns>
// 8 character string. The 1st six characters
// contain the encoded number, the last two
// characters are padded with "=".
// </returns>
public LSL_String llIntegerToBase64 ( int number )
{
// uninitialized string
char [ ] imdt = new char [ 8 ] ;
m_host . AddScriptLPS ( 1 ) ;
// Manually unroll the loop
imdt [ 7 ] = '=' ;
imdt [ 6 ] = '=' ;
imdt [ 5 ] = i2ctable [ number < < 4 & 0x3F ] ;
imdt [ 4 ] = i2ctable [ number > > 2 & 0x3F ] ;
imdt [ 3 ] = i2ctable [ number > > 8 & 0x3F ] ;
imdt [ 2 ] = i2ctable [ number > > 14 & 0x3F ] ;
imdt [ 1 ] = i2ctable [ number > > 20 & 0x3F ] ;
imdt [ 0 ] = i2ctable [ number > > 26 & 0x3F ] ;
return new string ( imdt ) ;
}
// <summary>
// Converts an eight character base-64 string
// into a 32-bit integer.
// </summary>
// <param name="str">
// 8 characters string to be converted. Other
// length strings return zero.
// </param>
// <returns>
// Returns an integer representing the
// encoded value providedint he 1st 6
// characters of the string.
// </returns>
// <remarks>
// This is coded to behave like LSL's
// implementation (I think), based upon the
// information available at the Wiki.
// If more than 8 characters are supplied,
// zero is returned.
// If a NULL string is supplied, zero will
// be returned.
// If fewer than 6 characters are supplied, then
// the answer will reflect a partial
// accumulation.
// <para>
// The 6-bit segments are
// extracted left-to-right in big-endian mode,
// which means that segment 6 only contains the
// two low-order bits of the 32 bit integer as
// its high order 2 bits. A short string therefore
// means loss of low-order information. E.g.
/ /
// |<---------------------- 32-bit integer ----------------------->|<-Pad->|
// |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
// |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
// |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
// | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
/ /
// </para>
// </remarks>
public LSL_Integer llBase64ToInteger ( string str )
{
int number = 0 ;
int digit ;
m_host . AddScriptLPS ( 1 ) ;
// Require a well-fromed base64 string
if ( str . Length > 8 )
return 0 ;
// The loop is unrolled in the interests
// of performance and simple necessity.
/ /
// MUST find 6 digits to be well formed
// -1 == invalid
// 0 == padding
2009-09-16 14:33:42 +00:00
if ( ( digit = c2itable [ str [ 0 ] ] ) < = 0 )
2008-09-26 02:51:00 +00:00
{
2009-09-16 14:33:42 +00:00
return digit < 0 ? ( int ) 0 : number ;
2008-09-26 02:51:00 +00:00
}
number + = - - digit < < 26 ;
2009-09-16 14:33:42 +00:00
if ( ( digit = c2itable [ str [ 1 ] ] ) < = 0 )
2008-09-26 02:51:00 +00:00
{
2009-09-16 14:33:42 +00:00
return digit < 0 ? ( int ) 0 : number ;
2008-09-26 02:51:00 +00:00
}
number + = - - digit < < 20 ;
2009-09-16 14:33:42 +00:00
if ( ( digit = c2itable [ str [ 2 ] ] ) < = 0 )
2008-09-26 02:51:00 +00:00
{
2009-09-16 14:33:42 +00:00
return digit < 0 ? ( int ) 0 : number ;
2008-09-26 02:51:00 +00:00
}
number + = - - digit < < 14 ;
2009-09-16 14:33:42 +00:00
if ( ( digit = c2itable [ str [ 3 ] ] ) < = 0 )
2008-09-26 02:51:00 +00:00
{
2009-09-16 14:33:42 +00:00
return digit < 0 ? ( int ) 0 : number ;
2008-09-26 02:51:00 +00:00
}
number + = - - digit < < 8 ;
2009-09-16 14:33:42 +00:00
if ( ( digit = c2itable [ str [ 4 ] ] ) < = 0 )
2008-09-26 02:51:00 +00:00
{
2009-09-16 14:33:42 +00:00
return digit < 0 ? ( int ) 0 : number ;
2008-09-26 02:51:00 +00:00
}
number + = - - digit < < 2 ;
2009-09-16 14:33:42 +00:00
if ( ( digit = c2itable [ str [ 5 ] ] ) < = 0 )
2008-09-26 02:51:00 +00:00
{
2009-09-16 14:33:42 +00:00
return digit < 0 ? ( int ) 0 : number ;
2008-09-26 02:51:00 +00:00
}
number + = - - digit > > 4 ;
// ignore trailing padding
return number ;
}
public LSL_Float llGetGMTclock ( )
{
m_host . AddScriptLPS ( 1 ) ;
return DateTime . UtcNow . TimeOfDay . TotalSeconds ;
}
2009-05-13 01:58:17 +00:00
public LSL_String llGetHTTPHeader ( LSL_Key request_id , string header )
{
m_host . AddScriptLPS ( 1 ) ;
2010-09-24 14:26:53 +00:00
2009-09-23 18:55:22 +00:00
if ( m_UrlModule ! = null )
2009-09-22 16:04:34 +00:00
return m_UrlModule . GetHttpHeader ( new UUID ( request_id ) , header ) ;
return String . Empty ;
2009-05-13 01:58:17 +00:00
}
2008-09-26 02:51:00 +00:00
public LSL_String llGetSimulatorHostname ( )
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-23 19:07:03 +00:00
IUrlModule UrlModule = World . RequestModuleInterface < IUrlModule > ( ) ;
return UrlModule . ExternalHostNameForLSL ;
2008-09-26 02:51:00 +00:00
}
// <summary>
// Scan the string supplied in 'src' and
// tokenize it based upon two sets of
// tokenizers provided in two lists,
// separators and spacers.
// </summary>
/ /
// <remarks>
// Separators demarcate tokens and are
// elided as they are encountered. Spacers
// also demarcate tokens, but are themselves
// retained as tokens.
/ /
// Both separators and spacers may be arbitrarily
// long strings. i.e. ":::".
/ /
// The function returns an ordered list
// representing the tokens found in the supplied
// sources string. If two successive tokenizers
// are encountered, then a NULL entry is added
// to the list.
/ /
// It is a precondition that the source and
// toekizer lisst are non-null. If they are null,
// then a null pointer exception will be thrown
// while their lengths are being determined.
/ /
// A small amount of working memoryis required
// of approximately 8*#tokenizers.
/ /
// There are many ways in which this function
// can be implemented, this implementation is
// fairly naive and assumes that when the
// function is invooked with a short source
// string and/or short lists of tokenizers, then
// performance will not be an issue.
/ /
// In order to minimize the perofrmance
// effects of long strings, or large numbers
// of tokeizers, the function skips as far as
// possible whenever a toekenizer is found,
// and eliminates redundant tokenizers as soon
// as is possible.
/ /
// The implementation tries to avoid any copying
// of arrays or other objects.
// </remarks>
2010-09-17 21:32:49 +00:00
private LSL_List ParseString ( string src , LSL_List separators , LSL_List spacers , bool keepNulls )
2008-09-26 02:51:00 +00:00
{
int beginning = 0 ;
int srclen = src . Length ;
int seplen = separators . Length ;
object [ ] separray = separators . Data ;
int spclen = spacers . Length ;
object [ ] spcarray = spacers . Data ;
int mlen = seplen + spclen ;
int [ ] offset = new int [ mlen + 1 ] ;
bool [ ] active = new bool [ mlen ] ;
int best ;
int j ;
// Initial capacity reduces resize cost
LSL_List tokens = new LSL_List ( ) ;
// All entries are initially valid
for ( int i = 0 ; i < mlen ; i + + )
active [ i ] = true ;
offset [ mlen ] = srclen ;
while ( beginning < srclen )
{
best = mlen ; // as bad as it gets
// Scan for separators
for ( j = 0 ; j < seplen ; j + + )
{
2010-10-21 06:19:10 +00:00
if ( separray [ j ] . ToString ( ) = = String . Empty )
active [ j ] = false ;
2008-09-26 02:51:00 +00:00
if ( active [ j ] )
{
// scan all of the markers
2009-09-16 14:33:42 +00:00
if ( ( offset [ j ] = src . IndexOf ( separray [ j ] . ToString ( ) , beginning ) ) = = - 1 )
2008-09-26 02:51:00 +00:00
{
// not present at all
active [ j ] = false ;
}
else
{
// present and correct
if ( offset [ j ] < offset [ best ] )
{
// closest so far
best = j ;
if ( offset [ best ] = = beginning )
break ;
}
}
}
}
// Scan for spacers
if ( offset [ best ] ! = beginning )
{
for ( j = seplen ; ( j < mlen ) & & ( offset [ best ] > beginning ) ; j + + )
{
2010-10-21 08:30:09 +00:00
if ( spcarray [ j - seplen ] . ToString ( ) = = String . Empty )
2010-10-21 06:19:10 +00:00
active [ j ] = false ;
2008-09-26 02:51:00 +00:00
if ( active [ j ] )
{
// scan all of the markers
if ( ( offset [ j ] = src . IndexOf ( spcarray [ j - seplen ] . ToString ( ) , beginning ) ) = = - 1 )
{
// not present at all
active [ j ] = false ;
}
else
{
// present and correct
if ( offset [ j ] < offset [ best ] )
{
// closest so far
best = j ;
}
}
}
}
}
// This is the normal exit from the scanning loop
if ( best = = mlen )
{
// no markers were found on this pass
// so we're pretty much done
2010-09-17 21:32:49 +00:00
if ( ( keepNulls ) | | ( ( ! keepNulls ) & & ( srclen - beginning ) > 0 ) )
tokens . Add ( new LSL_String ( src . Substring ( beginning , srclen - beginning ) ) ) ;
2008-09-26 02:51:00 +00:00
break ;
}
// Otherwise we just add the newly delimited token
// and recalculate where the search should continue.
2010-09-17 21:32:49 +00:00
if ( ( keepNulls ) | | ( ( ! keepNulls ) & & ( offset [ best ] - beginning ) > 0 ) )
tokens . Add ( new LSL_String ( src . Substring ( beginning , offset [ best ] - beginning ) ) ) ;
2008-09-26 02:51:00 +00:00
if ( best < seplen )
{
beginning = offset [ best ] + ( separray [ best ] . ToString ( ) ) . Length ;
}
else
{
beginning = offset [ best ] + ( spcarray [ best - seplen ] . ToString ( ) ) . Length ;
2010-09-17 21:32:49 +00:00
string str = spcarray [ best - seplen ] . ToString ( ) ;
if ( ( keepNulls ) | | ( ( ! keepNulls ) & & ( str . Length > 0 ) ) )
tokens . Add ( new LSL_String ( str ) ) ;
2008-09-26 02:51:00 +00:00
}
}
// This an awkward an not very intuitive boundary case. If the
// last substring is a tokenizer, then there is an implied trailing
// null list entry. Hopefully the single comparison will not be too
// arduous. Alternatively the 'break' could be replced with a return
// but that's shabby programming.
2010-09-17 21:32:49 +00:00
if ( ( beginning = = srclen ) & & ( keepNulls ) )
2008-09-26 02:51:00 +00:00
{
if ( srclen ! = 0 )
2008-11-08 15:31:02 +00:00
tokens . Add ( new LSL_String ( "" ) ) ;
2008-09-26 02:51:00 +00:00
}
return tokens ;
}
2010-09-24 14:26:53 +00:00
2010-09-17 21:32:49 +00:00
public LSL_List llParseString2List ( string src , LSL_List separators , LSL_List spacers )
{
m_host . AddScriptLPS ( 1 ) ;
return this . ParseString ( src , separators , spacers , false ) ;
}
2010-09-24 14:26:53 +00:00
2010-09-17 21:32:49 +00:00
public LSL_List llParseStringKeepNulls ( string src , LSL_List separators , LSL_List spacers )
{
m_host . AddScriptLPS ( 1 ) ;
return this . ParseString ( src , separators , spacers , true ) ;
}
2010-09-24 14:26:53 +00:00
2008-09-26 02:51:00 +00:00
public LSL_Integer llGetObjectPermMask ( int mask )
{
m_host . AddScriptLPS ( 1 ) ;
int permmask = 0 ;
if ( mask = = ScriptBaseClass . MASK_BASE ) //0
{
permmask = ( int ) m_host . BaseMask ;
}
else if ( mask = = ScriptBaseClass . MASK_OWNER ) //1
{
permmask = ( int ) m_host . OwnerMask ;
}
else if ( mask = = ScriptBaseClass . MASK_GROUP ) //2
{
permmask = ( int ) m_host . GroupMask ;
}
else if ( mask = = ScriptBaseClass . MASK_EVERYONE ) //3
{
permmask = ( int ) m_host . EveryoneMask ;
}
else if ( mask = = ScriptBaseClass . MASK_NEXT ) //4
{
permmask = ( int ) m_host . NextOwnerMask ;
}
return permmask ;
}
public void llSetObjectPermMask ( int mask , int value )
{
m_host . AddScriptLPS ( 1 ) ;
2009-06-06 16:39:28 +00:00
if ( m_ScriptEngine . Config . GetBoolean ( "AllowGodFunctions" , false ) )
2008-09-26 02:51:00 +00:00
{
2008-11-21 22:14:57 +00:00
if ( World . Permissions . CanRunConsoleCommand ( m_host . OwnerID ) )
2008-09-26 02:51:00 +00:00
{
if ( mask = = ScriptBaseClass . MASK_BASE ) //0
{
m_host . BaseMask = ( uint ) value ;
}
else if ( mask = = ScriptBaseClass . MASK_OWNER ) //1
{
m_host . OwnerMask = ( uint ) value ;
}
else if ( mask = = ScriptBaseClass . MASK_GROUP ) //2
{
m_host . GroupMask = ( uint ) value ;
}
else if ( mask = = ScriptBaseClass . MASK_EVERYONE ) //3
{
m_host . EveryoneMask = ( uint ) value ;
}
else if ( mask = = ScriptBaseClass . MASK_NEXT ) //4
{
m_host . NextOwnerMask = ( uint ) value ;
}
}
}
}
2012-07-04 20:42:04 +00:00
public LSL_Integer llGetInventoryPermMask ( string itemName , int mask )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
2012-07-04 20:42:04 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( itemName ) ;
if ( item = = null )
return - 1 ;
switch ( mask )
{
case 0 :
return ( int ) item . BasePermissions ;
case 1 :
return ( int ) item . CurrentPermissions ;
case 2 :
return ( int ) item . GroupPermissions ;
case 3 :
return ( int ) item . EveryonePermissions ;
case 4 :
return ( int ) item . NextPermissions ;
2008-09-26 02:51:00 +00:00
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
return - 1 ;
}
2009-12-31 06:41:10 +00:00
2012-07-04 20:47:20 +00:00
public void llSetInventoryPermMask ( string itemName , int mask , int value )
2008-09-26 02:51:00 +00:00
{
2009-12-31 06:41:10 +00:00
m_host . AddScriptLPS ( 1 ) ;
2012-07-04 20:47:20 +00:00
2010-02-14 21:41:57 +00:00
if ( m_ScriptEngine . Config . GetBoolean ( "AllowGodFunctions" , false ) )
2010-02-15 10:15:03 +00:00
{
if ( World . Permissions . CanRunConsoleCommand ( m_host . OwnerID ) )
{
2012-07-04 20:47:20 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( itemName ) ;
if ( item ! = null )
2010-02-15 10:15:03 +00:00
{
2012-07-04 20:47:20 +00:00
switch ( mask )
2010-02-15 10:15:03 +00:00
{
2012-07-04 20:47:20 +00:00
case 0 :
item . BasePermissions = ( uint ) value ;
break ;
case 1 :
item . CurrentPermissions = ( uint ) value ;
break ;
case 2 :
item . GroupPermissions = ( uint ) value ;
break ;
case 3 :
item . EveryonePermissions = ( uint ) value ;
break ;
case 4 :
item . NextPermissions = ( uint ) value ;
break ;
2010-02-15 10:15:03 +00:00
}
}
}
}
2008-09-26 02:51:00 +00:00
}
2012-07-04 20:49:21 +00:00
public LSL_String llGetInventoryCreator ( string itemName )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
2012-07-04 20:49:21 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( itemName ) ;
if ( item = = null )
2008-09-26 02:51:00 +00:00
{
2012-07-04 20:49:21 +00:00
llSay ( 0 , "No item name '" + item + "'" ) ;
2009-07-28 09:40:07 +00:00
2012-07-04 20:49:21 +00:00
return String . Empty ;
}
2009-07-28 09:40:07 +00:00
2012-07-04 20:49:21 +00:00
return item . CreatorID . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public void llOwnerSay ( string msg )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
World . SimChatBroadcast ( Utils . StringToBytes ( msg ) , ChatTypeEnum . Owner , 0 ,
2008-10-20 17:31:54 +00:00
m_host . AbsolutePosition , m_host . Name , m_host . UUID , false ) ;
2008-09-26 02:51:00 +00:00
// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
}
2009-05-13 01:13:59 +00:00
public LSL_String llRequestSecureURL ( )
2009-05-13 01:06:06 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2009-05-13 03:09:30 +00:00
if ( m_UrlModule ! = null )
2012-05-08 21:58:34 +00:00
return m_UrlModule . RequestSecureURL ( m_ScriptEngine . ScriptModule , m_host , m_item . ItemID ) . ToString ( ) ;
2009-05-13 01:06:06 +00:00
return UUID . Zero . ToString ( ) ;
}
2008-09-26 02:51:00 +00:00
public LSL_String llRequestSimulatorData ( string simulator , int data )
{
2012-05-08 21:58:34 +00:00
IOSSL_Api ossl = ( IOSSL_Api ) m_ScriptEngine . GetApi ( m_item . ItemID , "OSSL" ) ;
2008-10-03 06:15:23 +00:00
2008-09-26 02:51:00 +00:00
try
{
m_host . AddScriptLPS ( 1 ) ;
string reply = String . Empty ;
2010-08-19 18:41:55 +00:00
GridRegion info ;
2012-05-23 11:38:03 +00:00
if ( m_ScriptEngine . World . RegionInfo . RegionName = = simulator ) //Det data for this simulator?
2010-08-19 18:41:55 +00:00
info = new GridRegion ( m_ScriptEngine . World . RegionInfo ) ;
else
info = m_ScriptEngine . World . GridService . GetRegionByName ( m_ScriptEngine . World . RegionInfo . ScopeID , simulator ) ;
2008-09-26 02:51:00 +00:00
switch ( data )
{
2010-11-16 12:46:26 +00:00
case ScriptBaseClass . DATA_SIM_POS :
2008-09-26 02:51:00 +00:00
if ( info = = null )
{
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
return UUID . Zero . ToString ( ) ;
}
2012-05-23 11:38:03 +00:00
if ( m_ScriptEngine . World . RegionInfo . RegionName ! = simulator )
{
//Hypergrid Region co-ordinates
uint rx = 0 , ry = 0 ;
Utils . LongToUInts ( Convert . ToUInt64 ( info . RegionSecret ) , out rx , out ry ) ;
reply = new LSL_Vector (
rx ,
ry ,
0 ) . ToString ( ) ;
}
else
{
//Local-cooridnates
reply = new LSL_Vector (
info . RegionLocX ,
info . RegionLocY ,
0 ) . ToString ( ) ;
}
2008-09-26 02:51:00 +00:00
break ;
2010-11-16 12:46:26 +00:00
case ScriptBaseClass . DATA_SIM_STATUS :
2008-09-26 02:51:00 +00:00
if ( info ! = null )
reply = "up" ; // Duh!
else
reply = "unknown" ;
break ;
2010-11-16 12:46:26 +00:00
case ScriptBaseClass . DATA_SIM_RATING :
2008-09-26 02:51:00 +00:00
if ( info = = null )
{
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
return UUID . Zero . ToString ( ) ;
}
2009-09-26 14:48:21 +00:00
int access = info . Maturity ;
2008-09-26 02:51:00 +00:00
if ( access = = 0 )
reply = "PG" ;
else if ( access = = 1 )
reply = "MATURE" ;
2009-05-12 03:30:37 +00:00
else if ( access = = 2 )
reply = "ADULT" ;
2008-09-26 02:51:00 +00:00
else
reply = "UNKNOWN" ;
break ;
2010-11-16 12:46:26 +00:00
case ScriptBaseClass . DATA_SIM_RELEASE :
2008-10-03 06:15:23 +00:00
if ( ossl ! = null )
ossl . CheckThreatLevel ( ThreatLevel . High , "llRequestSimulatorData" ) ;
reply = "OpenSim" ;
break ;
2008-09-26 02:51:00 +00:00
default :
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
return UUID . Zero . ToString ( ) ; // Raise no event
}
UUID rq = UUID . Random ( ) ;
UUID tid = AsyncCommands .
2012-05-08 22:20:27 +00:00
DataserverPlugin . RegisterRequest ( m_host . LocalId , m_item . ItemID , rq . ToString ( ) ) ;
2008-09-26 02:51:00 +00:00
AsyncCommands .
DataserverPlugin . DataserverReply ( rq . ToString ( ) , reply ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
return tid . ToString ( ) ;
}
2009-05-22 14:57:00 +00:00
catch ( Exception )
2008-09-26 02:51:00 +00:00
{
2009-05-18 15:32:06 +00:00
//m_log.Error("[LSL_API]: llRequestSimulatorData" + e.ToString());
2008-09-26 02:51:00 +00:00
return UUID . Zero . ToString ( ) ;
}
}
2009-05-13 00:58:01 +00:00
public LSL_String llRequestURL ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-05-13 03:09:30 +00:00
if ( m_UrlModule ! = null )
2012-05-08 21:58:34 +00:00
return m_UrlModule . RequestURL ( m_ScriptEngine . ScriptModule , m_host , m_item . ItemID ) . ToString ( ) ;
2009-05-13 00:58:01 +00:00
return UUID . Zero . ToString ( ) ;
}
2008-09-26 02:51:00 +00:00
public void llForceMouselook ( int mouselook )
{
m_host . AddScriptLPS ( 1 ) ;
m_host . SetForceMouselook ( mouselook ! = 0 ) ;
}
public LSL_Float llGetObjectMass ( string id )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key = new UUID ( ) ;
if ( UUID . TryParse ( id , out key ) )
{
try
{
SceneObjectPart obj = World . GetSceneObjectPart ( World . Entities [ key ] . LocalId ) ;
if ( obj ! = null )
return ( double ) obj . GetMass ( ) ;
// the object is null so the key is for an avatar
ScenePresence avatar = World . GetScenePresence ( key ) ;
if ( avatar ! = null )
if ( avatar . IsChildAgent )
// reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
// child agents have a mass of 1.0
return 1 ;
else
2012-04-16 19:24:56 +00:00
return ( double ) avatar . GetMass ( ) ;
2008-09-26 02:51:00 +00:00
}
catch ( KeyNotFoundException )
{
return 0 ; // The Object/Agent not in the region so just return zero
}
}
return 0 ;
}
/// <summary>
/// illListReplaceList removes the sub-list defined by the inclusive indices
/// start and end and inserts the src list in its place. The inclusive
/// nature of the indices means that at least one element must be deleted
/// if the indices are within the bounds of the existing list. I.e. 2,2
/// will remove the element at index 2 and replace it with the source
/// list. Both indices may be negative, with the usual interpretation. An
/// interesting case is where end is lower than start. As these indices
/// bound the list to be removed, then 0->end, and start->lim are removed
/// and the source list is added as a suffix.
/// </summary>
public LSL_List llListReplaceList ( LSL_List dest , LSL_List src , int start , int end )
{
LSL_List pref = null ;
m_host . AddScriptLPS ( 1 ) ;
// Note that although we have normalized, both
// indices could still be negative.
if ( start < 0 )
{
start = start + dest . Length ;
}
if ( end < 0 )
{
end = end + dest . Length ;
}
// The comventional case, remove a sequence starting with
// start and ending with end. And then insert the source
// list.
if ( start < = end )
{
// If greater than zero, then there is going to be a
// surviving prefix. Otherwise the inclusive nature
// of the indices mean that we're going to add the
// source list as a prefix.
if ( start > 0 )
{
pref = dest . GetSublist ( 0 , start - 1 ) ;
// Only add a suffix if there is something
// beyond the end index (it's inclusive too).
if ( end + 1 < dest . Length )
{
return pref + src + dest . GetSublist ( end + 1 , - 1 ) ;
}
else
{
return pref + src ;
}
}
// If start is less than or equal to zero, then
// the new list is simply a prefix. We still need to
// figure out any necessary surgery to the destination
// based upon end. Note that if end exceeds the upper
// bound in this case, the entire destination list
// is removed.
else
{
if ( end + 1 < dest . Length )
{
return src + dest . GetSublist ( end + 1 , - 1 ) ;
}
else
{
return src ;
}
}
}
// Finally, if start > end, we strip away a prefix and
// a suffix, to leave the list that sits <between> ens
// and start, and then tag on the src list. AT least
// that's my interpretation. We can get sublist to do
// this for us. Note that one, or both of the indices
// might have been negative.
else
{
return dest . GetSublist ( end + 1 , start - 1 ) + src ;
}
}
public void llLoadURL ( string avatar_id , string message , string url )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
2009-01-08 19:28:10 +00:00
IDialogModule dm = World . RequestModuleInterface < IDialogModule > ( ) ;
if ( null ! = dm )
dm . SendUrlToUser (
2009-10-15 23:35:27 +00:00
new UUID ( avatar_id ) , m_host . Name , m_host . UUID , m_host . OwnerID , false , message , url ) ;
2009-01-08 19:28:10 +00:00
2009-10-22 04:42:34 +00:00
ScriptSleep ( 10000 ) ;
2008-09-26 02:51:00 +00:00
}
public void llParcelMediaCommandList ( LSL_List commandList )
{
2008-10-11 15:18:55 +00:00
// TODO: Not implemented yet (missing in libomv?):
// PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
2008-10-11 15:18:55 +00:00
// according to the docs, this command only works if script owner and land owner are the same
2008-10-11 20:53:33 +00:00
// lets add estate owners and gods, too, and use the generic permission check.
ILandObject landObject = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) ;
2010-12-13 20:35:56 +00:00
if ( ! World . Permissions . CanEditParcelProperties ( m_host . OwnerID , landObject , GroupPowers . ChangeMedia ) ) return ;
2008-10-11 15:18:55 +00:00
2009-07-28 09:40:07 +00:00
bool update = false ; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
2009-03-17 18:18:24 +00:00
byte loop = 0 ;
2008-10-11 20:53:33 +00:00
2009-10-02 09:10:52 +00:00
LandData landData = landObject . LandData ;
2008-10-11 15:18:55 +00:00
string url = landData . MediaURL ;
string texture = landData . MediaID . ToString ( ) ;
2009-07-28 09:40:07 +00:00
bool autoAlign = landData . MediaAutoScale ! = 0 ;
2008-10-11 15:18:55 +00:00
string mediaType = "" ; // TODO these have to be added as soon as LandData supports it
string description = "" ;
int width = 0 ;
int height = 0 ;
2009-07-28 09:40:07 +00:00
2008-10-11 15:18:55 +00:00
ParcelMediaCommandEnum ? commandToSend = null ;
float time = 0.0f ; // default is from start
2009-07-28 09:40:07 +00:00
2008-10-11 15:18:55 +00:00
ScenePresence presence = null ;
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
for ( int i = 0 ; i < commandList . Data . Length ; i + + )
{
2008-10-11 15:18:55 +00:00
ParcelMediaCommandEnum command = ( ParcelMediaCommandEnum ) commandList . Data [ i ] ;
switch ( command )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Agent :
// we send only to one agent
if ( ( i + 1 ) < commandList . Length )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
if ( commandList . Data [ i + 1 ] is LSL_String )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
UUID agentID ;
if ( UUID . TryParse ( ( LSL_String ) commandList . Data [ i + 1 ] , out agentID ) )
{
presence = World . GetScenePresence ( agentID ) ;
}
2008-09-26 02:51:00 +00:00
}
2008-10-11 15:18:55 +00:00
else ShoutError ( "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key" ) ;
+ + i ;
2008-09-26 02:51:00 +00:00
}
break ;
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Loop :
2009-03-17 18:18:24 +00:00
loop = 1 ;
commandToSend = command ;
update = true ; //need to send the media update packet to set looping
break ;
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Play :
2009-03-17 18:18:24 +00:00
loop = 0 ;
commandToSend = command ;
update = true ; //need to send the media update packet to make sure it doesn't loop
break ;
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Pause :
2008-09-26 02:51:00 +00:00
case ParcelMediaCommandEnum . Stop :
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Unload :
commandToSend = command ;
break ;
2009-07-28 09:40:07 +00:00
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Url :
if ( ( i + 1 ) < commandList . Length )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
if ( commandList . Data [ i + 1 ] is LSL_String )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
url = ( LSL_String ) commandList . Data [ i + 1 ] ;
update = true ;
2008-09-26 02:51:00 +00:00
}
2008-10-11 15:18:55 +00:00
else ShoutError ( "The argument of PARCEL_MEDIA_COMMAND_URL must be a string." ) ;
+ + i ;
2008-09-26 02:51:00 +00:00
}
break ;
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Texture :
if ( ( i + 1 ) < commandList . Length )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
if ( commandList . Data [ i + 1 ] is LSL_String )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
texture = ( LSL_String ) commandList . Data [ i + 1 ] ;
update = true ;
2008-09-26 02:51:00 +00:00
}
2008-10-11 15:18:55 +00:00
else ShoutError ( "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key." ) ;
+ + i ;
2008-09-26 02:51:00 +00:00
}
break ;
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Time :
2008-09-26 02:51:00 +00:00
if ( ( i + 1 ) < commandList . Length )
{
2008-10-11 15:18:55 +00:00
if ( commandList . Data [ i + 1 ] is LSL_Float )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
time = ( float ) ( LSL_Float ) commandList . Data [ i + 1 ] ;
}
else ShoutError ( "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float." ) ;
+ + i ;
}
break ;
2008-09-26 02:51:00 +00:00
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . AutoAlign :
if ( ( i + 1 ) < commandList . Length )
{
if ( commandList . Data [ i + 1 ] is LSL_Integer )
{
autoAlign = ( LSL_Integer ) commandList . Data [ i + 1 ] ;
update = true ;
}
2008-09-26 02:51:00 +00:00
2008-10-11 15:18:55 +00:00
else ShoutError ( "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer." ) ;
+ + i ;
}
break ;
2008-09-26 02:51:00 +00:00
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Type :
if ( ( i + 1 ) < commandList . Length )
{
if ( commandList . Data [ i + 1 ] is LSL_String )
{
mediaType = ( LSL_String ) commandList . Data [ i + 1 ] ;
update = true ;
}
else ShoutError ( "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string." ) ;
+ + i ;
}
break ;
2008-09-26 02:51:00 +00:00
2008-10-11 15:18:55 +00:00
case ParcelMediaCommandEnum . Desc :
if ( ( i + 1 ) < commandList . Length )
{
if ( commandList . Data [ i + 1 ] is LSL_String )
{
description = ( LSL_String ) commandList . Data [ i + 1 ] ;
update = true ;
}
else ShoutError ( "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string." ) ;
+ + i ;
}
break ;
case ParcelMediaCommandEnum . Size :
if ( ( i + 2 ) < commandList . Length )
{
if ( commandList . Data [ i + 1 ] is LSL_Integer )
{
if ( commandList . Data [ i + 2 ] is LSL_Integer )
2008-09-26 02:51:00 +00:00
{
2008-10-11 15:18:55 +00:00
width = ( LSL_Integer ) commandList . Data [ i + 1 ] ;
height = ( LSL_Integer ) commandList . Data [ i + 2 ] ;
update = true ;
2008-09-26 02:51:00 +00:00
}
2008-10-11 15:18:55 +00:00
else ShoutError ( "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer." ) ;
2008-09-26 02:51:00 +00:00
}
2008-10-11 15:18:55 +00:00
else ShoutError ( "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer." ) ;
i + = 2 ;
2008-09-26 02:51:00 +00:00
}
break ;
2008-10-11 15:18:55 +00:00
2008-09-26 02:51:00 +00:00
default :
2008-10-11 15:18:55 +00:00
NotImplemented ( "llParcelMediaCommandList parameter not supported yet: " + Enum . Parse ( typeof ( ParcelMediaCommandEnum ) , commandList . Data [ i ] . ToString ( ) ) . ToString ( ) ) ;
2008-09-26 02:51:00 +00:00
break ;
} //end switch
2008-10-11 15:18:55 +00:00
} //end for
2008-09-26 02:51:00 +00:00
2008-10-11 15:18:55 +00:00
// if we didn't get a presence, we send to all and change the url
// if we did get a presence, we only send to the agent specified, and *don't change the land settings*!
2009-07-28 09:40:07 +00:00
2008-10-11 15:18:55 +00:00
// did something important change or do we only start/stop/pause?
if ( update )
{
if ( presence = = null )
{
// we send to all
landData . MediaID = new UUID ( texture ) ;
landData . MediaAutoScale = autoAlign ? ( byte ) 1 : ( byte ) 0 ;
2010-08-30 01:28:31 +00:00
landData . MediaWidth = width ;
landData . MediaHeight = height ;
2010-02-14 21:41:57 +00:00
landData . MediaType = mediaType ;
2009-07-28 09:40:07 +00:00
2008-10-11 15:18:55 +00:00
// do that one last, it will cause a ParcelPropertiesUpdate
2009-03-05 20:53:23 +00:00
landObject . SetMediaUrl ( url ) ;
2008-10-11 15:18:55 +00:00
2010-10-22 20:28:10 +00:00
// now send to all (non-child) agents in the parcel
2011-11-04 00:53:51 +00:00
World . ForEachRootScenePresence ( delegate ( ScenePresence sp )
2008-10-11 15:18:55 +00:00
{
2011-10-27 07:42:21 +00:00
if ( sp . currentParcelUUID = = landData . GlobalID )
2010-03-19 12:51:16 +00:00
{
sp . ControllingClient . SendParcelMediaUpdate ( landData . MediaURL ,
landData . MediaID ,
landData . MediaAutoScale ,
mediaType ,
description ,
width , height ,
loop ) ;
}
} ) ;
2008-10-11 15:18:55 +00:00
}
2008-10-12 03:16:49 +00:00
else if ( ! presence . IsChildAgent )
2008-10-11 15:18:55 +00:00
{
// we only send to one (root) agent
presence . ControllingClient . SendParcelMediaUpdate ( url ,
new UUID ( texture ) ,
autoAlign ? ( byte ) 1 : ( byte ) 0 ,
mediaType ,
description ,
width , height ,
2009-07-28 09:40:07 +00:00
loop ) ;
2008-10-11 15:18:55 +00:00
}
}
if ( commandToSend ! = null )
{
// the commandList contained a start/stop/... command, too
if ( presence = = null )
{
2010-10-22 20:28:10 +00:00
// send to all (non-child) agents in the parcel
2011-11-04 00:53:51 +00:00
World . ForEachRootScenePresence ( delegate ( ScenePresence sp )
2008-10-11 15:18:55 +00:00
{
2011-10-27 07:42:21 +00:00
if ( sp . currentParcelUUID = = landData . GlobalID )
2010-03-19 12:51:16 +00:00
{
sp . ControllingClient . SendParcelMediaCommand ( 0x4 , // TODO what is this?
( ParcelMediaCommandEnum ) commandToSend ,
time ) ;
}
} ) ;
2008-10-11 15:18:55 +00:00
}
2008-10-12 03:16:49 +00:00
else if ( ! presence . IsChildAgent )
2008-10-11 15:18:55 +00:00
{
presence . ControllingClient . SendParcelMediaCommand ( 0x4 , // TODO what is this?
( ParcelMediaCommandEnum ) commandToSend ,
time ) ;
}
2008-09-26 02:51:00 +00:00
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 2000 ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_List llParcelMediaQuery ( LSL_List aList )
{
m_host . AddScriptLPS ( 1 ) ;
LSL_List list = new LSL_List ( ) ;
//TO DO: make the implementation for the missing commands
//PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
for ( int i = 0 ; i < aList . Data . Length ; i + + )
{
if ( aList . Data [ i ] ! = null )
{
switch ( ( ParcelMediaCommandEnum ) aList . Data [ i ] )
{
case ParcelMediaCommandEnum . Url :
list . Add ( new LSL_String ( World . GetLandData ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) . MediaURL ) ) ;
break ;
case ParcelMediaCommandEnum . Desc :
list . Add ( new LSL_String ( World . GetLandData ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) . Description ) ) ;
break ;
case ParcelMediaCommandEnum . Texture :
list . Add ( new LSL_String ( World . GetLandData ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) . MediaID . ToString ( ) ) ) ;
break ;
2010-02-14 21:41:57 +00:00
case ParcelMediaCommandEnum . Type :
list . Add ( new LSL_String ( World . GetLandData ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) . MediaType ) ) ;
break ;
case ParcelMediaCommandEnum . Size :
2010-08-30 01:28:31 +00:00
list . Add ( new LSL_String ( World . GetLandData ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) . MediaWidth ) ) ;
list . Add ( new LSL_String ( World . GetLandData ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) . MediaHeight ) ) ;
2010-02-14 21:41:57 +00:00
break ;
2008-09-26 02:51:00 +00:00
default :
ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum . Url ;
NotImplemented ( "llParcelMediaQuery parameter do not supported yet: " + Enum . Parse ( mediaCommandEnum . GetType ( ) , aList . Data [ i ] . ToString ( ) ) . ToString ( ) ) ;
break ;
}
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 2000 ) ;
2008-09-26 02:51:00 +00:00
return list ;
}
public LSL_Integer llModPow ( int a , int b , int c )
{
m_host . AddScriptLPS ( 1 ) ;
Int64 tmp = 0 ;
Math . DivRem ( Convert . ToInt64 ( Math . Pow ( a , b ) ) , c , out tmp ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
return Convert . ToInt32 ( tmp ) ;
}
public LSL_Integer llGetInventoryType ( string name )
{
m_host . AddScriptLPS ( 1 ) ;
2009-07-28 09:40:07 +00:00
2012-07-04 20:50:52 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( name ) ;
2009-07-28 09:40:07 +00:00
2012-07-04 20:50:52 +00:00
if ( item = = null )
return - 1 ;
return item . Type ;
2008-09-26 02:51:00 +00:00
}
public void llSetPayPrice ( int price , LSL_List quick_pay_buttons )
{
m_host . AddScriptLPS ( 1 ) ;
if ( quick_pay_buttons . Data . Length < 4 )
{
LSLError ( "List must have at least 4 elements" ) ;
return ;
}
m_host . ParentGroup . RootPart . PayPrice [ 0 ] = price ;
m_host . ParentGroup . RootPart . PayPrice [ 1 ] = ( LSL_Integer ) quick_pay_buttons . Data [ 0 ] ;
m_host . ParentGroup . RootPart . PayPrice [ 2 ] = ( LSL_Integer ) quick_pay_buttons . Data [ 1 ] ;
m_host . ParentGroup . RootPart . PayPrice [ 3 ] = ( LSL_Integer ) quick_pay_buttons . Data [ 2 ] ;
m_host . ParentGroup . RootPart . PayPrice [ 4 ] = ( LSL_Integer ) quick_pay_buttons . Data [ 3 ] ;
m_host . ParentGroup . HasGroupChanged = true ;
}
public LSL_Vector llGetCameraPos ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-02-20 14:04:29 +00:00
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter = = UUID . Zero )
2012-04-23 21:52:46 +00:00
return new LSL_Vector ( ) ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_TRACK_CAMERA ) = = 0 )
2012-04-23 21:52:46 +00:00
{
ShoutError ( "No permissions to track the camera" ) ;
return new LSL_Vector ( ) ;
2008-09-26 02:51:00 +00:00
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
ScenePresence presence = World . GetScenePresence ( m_host . OwnerID ) ;
if ( presence ! = null )
{
LSL_Vector pos = new LSL_Vector ( presence . CameraPosition . X , presence . CameraPosition . Y , presence . CameraPosition . Z ) ;
return pos ;
}
return new LSL_Vector ( ) ;
}
public LSL_Rotation llGetCameraRot ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-02-20 14:04:29 +00:00
2012-05-08 21:58:34 +00:00
if ( m_item . PermsGranter = = UUID . Zero )
2012-04-23 21:52:46 +00:00
return new LSL_Rotation ( ) ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_TRACK_CAMERA ) = = 0 )
2012-04-23 21:52:46 +00:00
{
ShoutError ( "No permissions to track the camera" ) ;
return new LSL_Rotation ( ) ;
2008-10-15 04:42:28 +00:00
}
2009-07-28 09:40:07 +00:00
2008-10-15 04:42:28 +00:00
ScenePresence presence = World . GetScenePresence ( m_host . OwnerID ) ;
if ( presence ! = null )
{
return new LSL_Rotation ( presence . CameraRotation . X , presence . CameraRotation . Y , presence . CameraRotation . Z , presence . CameraRotation . W ) ;
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
return new LSL_Rotation ( ) ;
}
2008-11-08 21:25:26 +00:00
/// <summary>
/// The SL implementation does nothing, it is deprecated
/// This duplicates SL
/// </summary>
2008-09-30 01:59:51 +00:00
public void llSetPrimURL ( string url )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 2000 ) ;
2008-09-26 02:51:00 +00:00
}
2008-11-08 21:25:26 +00:00
/// <summary>
/// The SL implementation shouts an error, it is deprecated
/// This duplicates SL
/// </summary>
2008-09-26 02:51:00 +00:00
public void llRefreshPrimURL ( )
{
m_host . AddScriptLPS ( 1 ) ;
2008-11-08 21:25:26 +00:00
ShoutError ( "llRefreshPrimURL - not yet supported" ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 20000 ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llEscapeURL ( string url )
{
m_host . AddScriptLPS ( 1 ) ;
try
{
2009-06-21 19:06:19 +00:00
return Uri . EscapeDataString ( url ) ;
2008-09-26 02:51:00 +00:00
}
catch ( Exception ex )
{
return "llEscapeURL: " + ex . ToString ( ) ;
}
}
public LSL_String llUnescapeURL ( string url )
{
m_host . AddScriptLPS ( 1 ) ;
try
{
return Uri . UnescapeDataString ( url ) ;
}
catch ( Exception ex )
{
return "llUnescapeURL: " + ex . ToString ( ) ;
}
}
2008-10-01 21:30:48 +00:00
public void llMapDestination ( string simname , LSL_Vector pos , LSL_Vector lookAt )
2008-09-26 02:51:00 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2012-05-08 21:58:34 +00:00
DetectParams detectedParams = m_ScriptEngine . GetDetectParams ( m_item . ItemID , 0 ) ;
2008-11-08 23:55:40 +00:00
if ( detectedParams = = null ) return ; // only works on the first detected avatar
2008-10-01 21:30:48 +00:00
2008-11-08 23:55:40 +00:00
ScenePresence avatar = World . GetScenePresence ( detectedParams . Key ) ;
2008-10-01 21:30:48 +00:00
if ( avatar ! = null )
{
2012-08-18 00:17:01 +00:00
avatar . ControllingClient . SendScriptTeleportRequest ( m_host . Name ,
simname , pos , lookAt ) ;
2008-10-01 21:30:48 +00:00
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 1000 ) ;
2008-09-26 02:51:00 +00:00
}
public void llAddToLandBanList ( string avatar , double hours )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key ;
2010-12-13 20:35:56 +00:00
ILandObject land = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) ;
if ( World . Permissions . CanEditParcelProperties ( m_host . OwnerID , land , GroupPowers . LandManageBanned ) )
2008-09-26 02:51:00 +00:00
{
2012-02-02 23:40:56 +00:00
int expires = 0 ;
if ( hours ! = 0 )
expires = Util . UnixTimeSinceEpoch ( ) + ( int ) ( 3600.0 * hours ) ;
2008-09-26 02:51:00 +00:00
if ( UUID . TryParse ( avatar , out key ) )
{
2012-02-02 23:40:56 +00:00
int idx = land . LandData . ParcelAccessList . FindIndex (
delegate ( LandAccessEntry e )
2010-12-13 20:35:56 +00:00
{
if ( e . AgentID = = key & & e . Flags = = AccessList . Ban )
return true ;
return false ;
2012-02-02 23:40:56 +00:00
} ) ;
if ( idx ! = - 1 & & ( land . LandData . ParcelAccessList [ idx ] . Expires = = 0 | | ( expires ! = 0 & & expires < land . LandData . ParcelAccessList [ idx ] . Expires ) ) )
return ;
if ( idx ! = - 1 )
land . LandData . ParcelAccessList . RemoveAt ( idx ) ;
LandAccessEntry entry = new LandAccessEntry ( ) ;
entry . AgentID = key ;
entry . Flags = AccessList . Ban ;
entry . Expires = expires ;
land . LandData . ParcelAccessList . Add ( entry ) ;
World . EventManager . TriggerLandObjectUpdated ( ( uint ) land . LandData . LocalID , land ) ;
2008-09-26 02:51:00 +00:00
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public void llRemoveFromLandPassList ( string avatar )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key ;
2010-12-13 20:35:56 +00:00
ILandObject land = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) ;
if ( World . Permissions . CanEditParcelProperties ( m_host . OwnerID , land , GroupPowers . LandManageAllowed ) )
2008-09-26 02:51:00 +00:00
{
if ( UUID . TryParse ( avatar , out key ) )
{
2010-12-13 20:35:56 +00:00
int idx = land . LandData . ParcelAccessList . FindIndex (
2012-02-02 23:40:56 +00:00
delegate ( LandAccessEntry e )
2010-12-13 20:35:56 +00:00
{
if ( e . AgentID = = key & & e . Flags = = AccessList . Access )
return true ;
return false ;
} ) ;
if ( idx ! = - 1 )
2012-02-02 23:40:56 +00:00
{
2010-12-13 20:35:56 +00:00
land . LandData . ParcelAccessList . RemoveAt ( idx ) ;
2012-02-02 23:40:56 +00:00
World . EventManager . TriggerLandObjectUpdated ( ( uint ) land . LandData . LocalID , land ) ;
}
2008-09-26 02:51:00 +00:00
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public void llRemoveFromLandBanList ( string avatar )
{
m_host . AddScriptLPS ( 1 ) ;
UUID key ;
2010-12-13 20:35:56 +00:00
ILandObject land = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) ;
if ( World . Permissions . CanEditParcelProperties ( m_host . OwnerID , land , GroupPowers . LandManageBanned ) )
2008-09-26 02:51:00 +00:00
{
if ( UUID . TryParse ( avatar , out key ) )
{
2010-12-13 20:35:56 +00:00
int idx = land . LandData . ParcelAccessList . FindIndex (
2012-02-02 23:40:56 +00:00
delegate ( LandAccessEntry e )
2010-12-13 20:35:56 +00:00
{
if ( e . AgentID = = key & & e . Flags = = AccessList . Ban )
return true ;
return false ;
} ) ;
if ( idx ! = - 1 )
2012-02-02 23:40:56 +00:00
{
2010-12-13 20:35:56 +00:00
land . LandData . ParcelAccessList . RemoveAt ( idx ) ;
2012-02-02 23:40:56 +00:00
World . EventManager . TriggerLandObjectUpdated ( ( uint ) land . LandData . LocalID , land ) ;
}
2008-09-26 02:51:00 +00:00
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public void llSetCameraParams ( LSL_List rules )
{
m_host . AddScriptLPS ( 1 ) ;
// the object we are in
UUID objectID = m_host . ParentUUID ;
2012-04-23 21:52:46 +00:00
if ( objectID = = UUID . Zero )
return ;
2008-09-26 02:51:00 +00:00
2012-04-23 21:52:46 +00:00
// we need the permission first, to know which avatar we want to set the camera for
2012-05-08 21:58:34 +00:00
UUID agentID = m_item . PermsGranter ;
2012-04-23 21:52:46 +00:00
if ( agentID = = UUID . Zero )
return ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_CONTROL_CAMERA ) = = 0 )
2012-04-23 21:52:46 +00:00
return ;
2008-09-26 02:51:00 +00:00
ScenePresence presence = World . GetScenePresence ( agentID ) ;
// we are not interested in child-agents
if ( presence . IsChildAgent ) return ;
SortedDictionary < int , float > parameters = new SortedDictionary < int , float > ( ) ;
object [ ] data = rules . Data ;
for ( int i = 0 ; i < data . Length ; + + i ) {
int type = Convert . ToInt32 ( data [ i + + ] . ToString ( ) ) ;
if ( i > = data . Length ) break ; // odd number of entries => ignore the last
// some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
switch ( type ) {
case ScriptBaseClass . CAMERA_FOCUS :
case ScriptBaseClass . CAMERA_FOCUS_OFFSET :
case ScriptBaseClass . CAMERA_POSITION :
LSL_Vector v = ( LSL_Vector ) data [ i ] ;
parameters . Add ( type + 1 , ( float ) v . x ) ;
parameters . Add ( type + 2 , ( float ) v . y ) ;
parameters . Add ( type + 3 , ( float ) v . z ) ;
break ;
default :
// TODO: clean that up as soon as the implicit casts are in
if ( data [ i ] is LSL_Float )
parameters . Add ( type , ( float ) ( ( LSL_Float ) data [ i ] ) . value ) ;
else if ( data [ i ] is LSL_Integer )
parameters . Add ( type , ( float ) ( ( LSL_Integer ) data [ i ] ) . value ) ;
else parameters . Add ( type , Convert . ToSingle ( data [ i ] ) ) ;
break ;
}
}
if ( parameters . Count > 0 ) presence . ControllingClient . SendSetFollowCamProperties ( objectID , parameters ) ;
}
public void llClearCameraParams ( )
{
m_host . AddScriptLPS ( 1 ) ;
// the object we are in
UUID objectID = m_host . ParentUUID ;
2012-04-23 21:52:46 +00:00
if ( objectID = = UUID . Zero )
return ;
2008-09-26 02:51:00 +00:00
// we need the permission first, to know which avatar we want to clear the camera for
2012-05-08 21:58:34 +00:00
UUID agentID = m_item . PermsGranter ;
2012-04-23 21:52:46 +00:00
if ( agentID = = UUID . Zero )
return ;
2012-05-08 21:58:34 +00:00
if ( ( m_item . PermsMask & ScriptBaseClass . PERMISSION_CONTROL_CAMERA ) = = 0 )
2012-04-23 21:52:46 +00:00
return ;
2008-09-26 02:51:00 +00:00
ScenePresence presence = World . GetScenePresence ( agentID ) ;
// we are not interested in child-agents
2012-04-23 21:52:46 +00:00
if ( presence . IsChildAgent )
return ;
2008-09-26 02:51:00 +00:00
presence . ControllingClient . SendClearFollowCamProperties ( objectID ) ;
}
public LSL_Float llListStatistics ( int operation , LSL_List src )
{
m_host . AddScriptLPS ( 1 ) ;
LSL_List nums = LSL_List . ToDoubleList ( src ) ;
switch ( operation )
{
case ScriptBaseClass . LIST_STAT_RANGE :
return nums . Range ( ) ;
case ScriptBaseClass . LIST_STAT_MIN :
return nums . Min ( ) ;
case ScriptBaseClass . LIST_STAT_MAX :
return nums . Max ( ) ;
case ScriptBaseClass . LIST_STAT_MEAN :
return nums . Mean ( ) ;
case ScriptBaseClass . LIST_STAT_MEDIAN :
return nums . Median ( ) ;
case ScriptBaseClass . LIST_STAT_NUM_COUNT :
return nums . NumericLength ( ) ;
case ScriptBaseClass . LIST_STAT_STD_DEV :
return nums . StdDev ( ) ;
case ScriptBaseClass . LIST_STAT_SUM :
return nums . Sum ( ) ;
case ScriptBaseClass . LIST_STAT_SUM_SQUARES :
return nums . SumSqrs ( ) ;
case ScriptBaseClass . LIST_STAT_GEOMETRIC_MEAN :
return nums . GeometricMean ( ) ;
case ScriptBaseClass . LIST_STAT_HARMONIC_MEAN :
return nums . HarmonicMean ( ) ;
default :
return 0.0 ;
}
}
public LSL_Integer llGetUnixTime ( )
{
m_host . AddScriptLPS ( 1 ) ;
return Util . UnixTimeSinceEpoch ( ) ;
}
public LSL_Integer llGetParcelFlags ( LSL_Vector pos )
{
m_host . AddScriptLPS ( 1 ) ;
2009-10-02 09:10:52 +00:00
return ( int ) World . LandChannel . GetLandObject ( ( float ) pos . x , ( float ) pos . y ) . LandData . Flags ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llGetRegionFlags ( )
{
m_host . AddScriptLPS ( 1 ) ;
IEstateModule estate = World . RequestModuleInterface < IEstateModule > ( ) ;
if ( estate = = null )
return 67108864 ;
return ( int ) estate . GetRegionFlags ( ) ;
}
public LSL_String llXorBase64StringsCorrect ( string str1 , string str2 )
{
m_host . AddScriptLPS ( 1 ) ;
string ret = String . Empty ;
string src1 = llBase64ToString ( str1 ) ;
string src2 = llBase64ToString ( str2 ) ;
int c = 0 ;
for ( int i = 0 ; i < src1 . Length ; i + + )
{
2009-03-05 03:15:30 +00:00
ret + = ( char ) ( src1 [ i ] ^ src2 [ c ] ) ;
2008-09-26 02:51:00 +00:00
c + + ;
if ( c > = src2 . Length )
c = 0 ;
}
return llStringToBase64 ( ret ) ;
}
public LSL_String llHTTPRequest ( string url , LSL_List parameters , string body )
{
// Partial implementation: support for parameter flags needed
// see http://wiki.secondlife.com/wiki/LlHTTPRequest
// parameter flags support are implemented in ScriptsHttpRequests.cs
// in StartHttpRequest
m_host . AddScriptLPS ( 1 ) ;
2009-02-06 16:55:34 +00:00
IHttpRequestModule httpScriptMod =
m_ScriptEngine . World . RequestModuleInterface < IHttpRequestModule > ( ) ;
2008-09-26 02:51:00 +00:00
List < string > param = new List < string > ( ) ;
foreach ( object o in parameters . Data )
{
param . Add ( o . ToString ( ) ) ;
}
Vector3 position = m_host . AbsolutePosition ;
Vector3 velocity = m_host . Velocity ;
Quaternion rotation = m_host . RotationOffset ;
2009-04-18 14:21:54 +00:00
string ownerName = String . Empty ;
2009-10-15 23:35:27 +00:00
ScenePresence scenePresence = World . GetScenePresence ( m_host . OwnerID ) ;
2009-04-18 14:21:54 +00:00
if ( scenePresence = = null )
2009-10-15 23:35:27 +00:00
ownerName = resolveName ( m_host . OwnerID ) ;
2009-04-18 14:21:54 +00:00
else
ownerName = scenePresence . Name ;
2008-09-26 02:51:00 +00:00
RegionInfo regionInfo = World . RegionInfo ;
Dictionary < string , string > httpHeaders = new Dictionary < string , string > ( ) ;
2009-02-21 03:32:25 +00:00
string shard = "OpenSim" ;
2009-06-06 16:39:28 +00:00
IConfigSource config = m_ScriptEngine . ConfigSource ;
2009-02-21 00:14:47 +00:00
if ( config . Configs [ "Network" ] ! = null )
{
shard = config . Configs [ "Network" ] . GetString ( "shard" , shard ) ;
}
httpHeaders [ "X-SecondLife-Shard" ] = shard ;
2008-09-26 02:51:00 +00:00
httpHeaders [ "X-SecondLife-Object-Name" ] = m_host . Name ;
2009-02-21 17:50:46 +00:00
httpHeaders [ "X-SecondLife-Object-Key" ] = m_host . UUID . ToString ( ) ;
2008-09-26 02:51:00 +00:00
httpHeaders [ "X-SecondLife-Region" ] = string . Format ( "{0} ({1}, {2})" , regionInfo . RegionName , regionInfo . RegionLocX , regionInfo . RegionLocY ) ;
httpHeaders [ "X-SecondLife-Local-Position" ] = string . Format ( "({0:0.000000}, {1:0.000000}, {2:0.000000})" , position . X , position . Y , position . Z ) ;
httpHeaders [ "X-SecondLife-Local-Velocity" ] = string . Format ( "({0:0.000000}, {1:0.000000}, {2:0.000000})" , velocity . X , velocity . Y , velocity . Z ) ;
httpHeaders [ "X-SecondLife-Local-Rotation" ] = string . Format ( "({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})" , rotation . X , rotation . Y , rotation . Z , rotation . W ) ;
2009-04-18 14:21:54 +00:00
httpHeaders [ "X-SecondLife-Owner-Name" ] = ownerName ;
2009-10-15 23:35:27 +00:00
httpHeaders [ "X-SecondLife-Owner-Key" ] = m_host . OwnerID . ToString ( ) ;
2009-03-07 12:58:00 +00:00
string userAgent = config . Configs [ "Network" ] . GetString ( "user_agent" , null ) ;
if ( userAgent ! = null )
httpHeaders [ "User-Agent" ] = userAgent ;
2008-09-26 02:51:00 +00:00
2009-07-23 15:32:11 +00:00
string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$" ;
Regex r = new Regex ( authregex ) ;
int [ ] gnums = r . GetGroupNumbers ( ) ;
Match m = r . Match ( url ) ;
if ( m . Success ) {
for ( int i = 1 ; i < gnums . Length ; i + + ) {
2009-08-05 16:39:32 +00:00
//System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
2009-08-05 16:33:23 +00:00
//CaptureCollection cc = g.Captures;
2009-07-28 09:40:07 +00:00
}
2009-07-23 15:32:11 +00:00
if ( m . Groups . Count = = 5 ) {
httpHeaders [ "Authorization" ] = String . Format ( "Basic {0}" , Convert . ToBase64String ( System . Text . ASCIIEncoding . ASCII . GetBytes ( m . Groups [ 2 ] . ToString ( ) + ":" + m . Groups [ 3 ] . ToString ( ) ) ) ) ;
url = m . Groups [ 1 ] . ToString ( ) + m . Groups [ 4 ] . ToString ( ) ;
}
}
2009-07-18 20:10:19 +00:00
2012-05-08 22:20:27 +00:00
UUID reqID
= httpScriptMod . StartHttpRequest ( m_host . LocalId , m_item . ItemID , url , param , httpHeaders , body ) ;
2008-09-26 02:51:00 +00:00
if ( reqID ! = UUID . Zero )
return reqID . ToString ( ) ;
else
return null ;
}
2009-05-13 00:29:50 +00:00
2009-09-22 16:04:34 +00:00
public void llHTTPResponse ( LSL_Key id , int status , string body )
2009-05-13 00:29:50 +00:00
{
// Partial implementation: support for parameter flags needed
// see http://wiki.secondlife.com/wiki/llHTTPResponse
m_host . AddScriptLPS ( 1 ) ;
2009-09-23 18:55:22 +00:00
if ( m_UrlModule ! = null )
2009-09-22 16:04:34 +00:00
m_UrlModule . HttpResponse ( new UUID ( id ) , status , body ) ;
2009-05-13 00:29:50 +00:00
}
2009-07-28 09:40:07 +00:00
2008-09-26 02:51:00 +00:00
public void llResetLandBanList ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-10-02 09:10:52 +00:00
LandData land = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) . LandData ;
2008-09-26 02:51:00 +00:00
if ( land . OwnerID = = m_host . OwnerID )
{
2012-02-02 23:40:56 +00:00
foreach ( LandAccessEntry entry in land . ParcelAccessList )
2008-09-26 02:51:00 +00:00
{
2008-09-26 17:25:22 +00:00
if ( entry . Flags = = AccessList . Ban )
2008-09-26 02:51:00 +00:00
{
land . ParcelAccessList . Remove ( entry ) ;
}
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public void llResetLandPassList ( )
{
m_host . AddScriptLPS ( 1 ) ;
2009-10-02 09:10:52 +00:00
LandData land = World . LandChannel . GetLandObject ( m_host . AbsolutePosition . X , m_host . AbsolutePosition . Y ) . LandData ;
2008-09-26 02:51:00 +00:00
if ( land . OwnerID = = m_host . OwnerID )
{
2012-02-02 23:40:56 +00:00
foreach ( LandAccessEntry entry in land . ParcelAccessList )
2008-09-26 02:51:00 +00:00
{
2008-09-26 17:25:22 +00:00
if ( entry . Flags = = AccessList . Access )
2008-09-26 02:51:00 +00:00
{
land . ParcelAccessList . Remove ( entry ) ;
}
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_Integer llGetParcelPrimCount ( LSL_Vector pos , int category , int sim_wide )
{
m_host . AddScriptLPS ( 1 ) ;
2011-04-05 19:31:52 +00:00
ILandObject lo = World . LandChannel . GetLandObject ( ( float ) pos . x , ( float ) pos . y ) ;
2008-09-26 02:51:00 +00:00
2011-04-05 19:31:52 +00:00
if ( lo = = null )
return 0 ;
IPrimCounts pc = lo . PrimCounts ;
2008-09-26 02:51:00 +00:00
2011-04-05 19:39:58 +00:00
if ( sim_wide ! = ScriptBaseClass . FALSE )
2008-09-26 02:51:00 +00:00
{
2011-04-05 19:39:58 +00:00
if ( category = = ScriptBaseClass . PARCEL_COUNT_TOTAL )
2011-04-05 19:31:52 +00:00
{
return pc . Simulator ;
}
else
{
// counts not implemented yet
return 0 ;
}
2008-09-26 02:51:00 +00:00
}
else
{
2011-04-05 19:39:58 +00:00
if ( category = = ScriptBaseClass . PARCEL_COUNT_TOTAL )
2011-04-05 19:31:52 +00:00
return pc . Total ;
2011-04-05 19:39:58 +00:00
else if ( category = = ScriptBaseClass . PARCEL_COUNT_OWNER )
2011-04-05 19:31:52 +00:00
return pc . Owner ;
2011-04-05 19:39:58 +00:00
else if ( category = = ScriptBaseClass . PARCEL_COUNT_GROUP )
2011-04-05 19:31:52 +00:00
return pc . Group ;
2011-04-05 19:39:58 +00:00
else if ( category = = ScriptBaseClass . PARCEL_COUNT_OTHER )
2011-04-05 19:31:52 +00:00
return pc . Others ;
2011-04-05 19:39:58 +00:00
else if ( category = = ScriptBaseClass . PARCEL_COUNT_SELECTED )
2011-04-05 19:31:52 +00:00
return pc . Selected ;
2011-04-05 19:39:58 +00:00
else if ( category = = ScriptBaseClass . PARCEL_COUNT_TEMP )
2011-04-05 19:31:52 +00:00
return 0 ; // counts not implemented yet
2008-09-26 02:51:00 +00:00
}
2011-04-05 19:31:52 +00:00
2008-09-26 02:51:00 +00:00
return 0 ;
}
public LSL_List llGetParcelPrimOwners ( LSL_Vector pos )
{
m_host . AddScriptLPS ( 1 ) ;
LandObject land = ( LandObject ) World . LandChannel . GetLandObject ( ( float ) pos . x , ( float ) pos . y ) ;
LSL_List ret = new LSL_List ( ) ;
if ( land ! = null )
{
2009-10-02 09:10:52 +00:00
foreach ( KeyValuePair < UUID , int > detectedParams in land . GetLandObjectOwners ( ) )
2008-09-26 02:51:00 +00:00
{
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( detectedParams . Key . ToString ( ) ) ) ;
ret . Add ( new LSL_Integer ( detectedParams . Value ) ) ;
2008-09-26 02:51:00 +00:00
}
}
2009-10-22 04:42:34 +00:00
ScriptSleep ( 2000 ) ;
2008-09-26 02:51:00 +00:00
return ret ;
}
public LSL_Integer llGetObjectPrimCount ( string object_id )
{
m_host . AddScriptLPS ( 1 ) ;
SceneObjectPart part = World . GetSceneObjectPart ( new UUID ( object_id ) ) ;
if ( part = = null )
{
return 0 ;
}
else
{
2009-02-13 21:56:50 +00:00
return part . ParentGroup . PrimCount ;
2008-09-26 02:51:00 +00:00
}
}
public LSL_Integer llGetParcelMaxPrims ( LSL_Vector pos , int sim_wide )
{
m_host . AddScriptLPS ( 1 ) ;
2011-05-14 00:26:04 +00:00
2011-05-14 01:34:46 +00:00
ILandObject lo = World . LandChannel . GetLandObject ( ( float ) pos . x , ( float ) pos . y ) ;
2008-09-26 02:51:00 +00:00
2011-05-14 01:34:46 +00:00
if ( lo = = null )
2008-09-26 02:51:00 +00:00
return 0 ;
2009-04-02 10:24:12 +00:00
if ( sim_wide ! = 0 )
2011-05-14 01:42:47 +00:00
return lo . GetSimulatorMaxPrimCount ( ) ;
2008-09-26 02:51:00 +00:00
else
2011-05-14 01:42:47 +00:00
return lo . GetParcelMaxPrimCount ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_List llGetParcelDetails ( LSL_Vector pos , LSL_List param )
{
m_host . AddScriptLPS ( 1 ) ;
LandData land = World . GetLandData ( ( float ) pos . x , ( float ) pos . y ) ;
if ( land = = null )
{
return new LSL_List ( 0 ) ;
}
LSL_List ret = new LSL_List ( ) ;
foreach ( object o in param . Data )
{
switch ( o . ToString ( ) )
{
case "0" :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( land . Name ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case "1" :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( land . Description ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case "2" :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_Key ( land . OwnerID . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case "3" :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_Key ( land . GroupID . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
break ;
case "4" :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_Integer ( land . Area ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2010-11-08 17:15:20 +00:00
case "5" :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_Key ( land . GlobalID . ToString ( ) ) ) ;
2010-11-08 17:15:20 +00:00
break ;
2008-09-26 02:51:00 +00:00
default :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_Integer ( 0 ) ) ;
2008-09-26 02:51:00 +00:00
break ;
}
}
return ret ;
}
public LSL_String llStringTrim ( string src , int type )
{
m_host . AddScriptLPS ( 1 ) ;
if ( type = = ( int ) ScriptBaseClass . STRING_TRIM_HEAD ) { return src . TrimStart ( ) ; }
if ( type = = ( int ) ScriptBaseClass . STRING_TRIM_TAIL ) { return src . TrimEnd ( ) ; }
if ( type = = ( int ) ScriptBaseClass . STRING_TRIM ) { return src . Trim ( ) ; }
return src ;
}
public LSL_List llGetObjectDetails ( string id , LSL_List args )
{
m_host . AddScriptLPS ( 1 ) ;
2011-07-15 23:08:11 +00:00
2008-09-26 02:51:00 +00:00
LSL_List ret = new LSL_List ( ) ;
UUID key = new UUID ( ) ;
if ( UUID . TryParse ( id , out key ) )
{
ScenePresence av = World . GetScenePresence ( key ) ;
if ( av ! = null )
{
foreach ( object o in args . Data )
{
2011-07-15 23:08:11 +00:00
switch ( int . Parse ( o . ToString ( ) ) )
2008-09-26 02:51:00 +00:00
{
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_NAME :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( av . Firstname + " " + av . Lastname ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_DESC :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( "" ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_POS :
2008-09-26 02:51:00 +00:00
ret . Add ( new LSL_Vector ( ( double ) av . AbsolutePosition . X , ( double ) av . AbsolutePosition . Y , ( double ) av . AbsolutePosition . Z ) ) ;
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_ROT :
2008-09-26 02:51:00 +00:00
ret . Add ( new LSL_Rotation ( ( double ) av . Rotation . X , ( double ) av . Rotation . Y , ( double ) av . Rotation . Z , ( double ) av . Rotation . W ) ) ;
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_VELOCITY :
2008-09-26 02:51:00 +00:00
ret . Add ( new LSL_Vector ( av . Velocity . X , av . Velocity . Y , av . Velocity . Z ) ) ;
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_OWNER :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( id ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_GROUP :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( UUID . Zero . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_CREATOR :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( UUID . Zero . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2012-04-06 18:11:09 +00:00
// For the following 8 see the Object version below
case ScriptBaseClass . OBJECT_RUNNING_SCRIPT_COUNT :
2012-04-09 18:58:07 +00:00
ret . Add ( new LSL_Integer ( av . RunningScriptCount ( ) ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_TOTAL_SCRIPT_COUNT :
2012-04-09 18:58:07 +00:00
ret . Add ( new LSL_Integer ( av . ScriptCount ( ) ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_SCRIPT_MEMORY :
2012-04-09 18:58:07 +00:00
ret . Add ( new LSL_Integer ( av . RunningScriptCount ( ) * 16384 ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_SCRIPT_TIME :
2012-04-10 20:25:05 +00:00
ret . Add ( new LSL_Float ( av . ScriptExecutionTime ( ) / 1000.0f ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_PRIM_EQUIVALENCE :
2012-04-09 18:58:07 +00:00
ret . Add ( new LSL_Integer ( 1 ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_SERVER_COST :
ret . Add ( new LSL_Float ( 0 ) ) ;
break ;
case ScriptBaseClass . OBJECT_STREAMING_COST :
ret . Add ( new LSL_Float ( 0 ) ) ;
break ;
case ScriptBaseClass . OBJECT_PHYSICS_COST :
ret . Add ( new LSL_Float ( 0 ) ) ;
break ;
default :
// Invalid or unhandled constant.
ret . Add ( new LSL_Integer ( ScriptBaseClass . OBJECT_UNKNOWN_DETAIL ) ) ;
break ;
2008-09-26 02:51:00 +00:00
}
}
2011-07-15 22:36:32 +00:00
2008-09-26 02:51:00 +00:00
return ret ;
}
2011-07-15 22:36:32 +00:00
2008-09-26 02:51:00 +00:00
SceneObjectPart obj = World . GetSceneObjectPart ( key ) ;
if ( obj ! = null )
{
foreach ( object o in args . Data )
{
2011-07-15 23:08:11 +00:00
switch ( int . Parse ( o . ToString ( ) ) )
2008-09-26 02:51:00 +00:00
{
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_NAME :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( obj . Name ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_DESC :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( obj . Description ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_POS :
2008-09-26 02:51:00 +00:00
ret . Add ( new LSL_Vector ( obj . AbsolutePosition . X , obj . AbsolutePosition . Y , obj . AbsolutePosition . Z ) ) ;
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_ROT :
2012-07-29 15:05:35 +00:00
{
Quaternion rot = Quaternion . Identity ;
if ( obj . ParentGroup . RootPart = = obj )
rot = obj . ParentGroup . GroupRotation ;
else
rot = obj . GetWorldRotation ( ) ;
2012-08-18 14:04:07 +00:00
LSL_Rotation objrot = new LSL_Rotation ( rot ) ;
2012-07-29 15:05:35 +00:00
ret . Add ( objrot ) ;
}
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_VELOCITY :
2012-08-18 13:54:13 +00:00
ret . Add ( new LSL_Vector ( obj . Velocity ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_OWNER :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( obj . OwnerID . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_GROUP :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( obj . GroupID . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2011-07-15 23:08:11 +00:00
case ScriptBaseClass . OBJECT_CREATOR :
2011-07-04 13:45:21 +00:00
ret . Add ( new LSL_String ( obj . CreatorID . ToString ( ) ) ) ;
2008-09-26 02:51:00 +00:00
break ;
2012-04-06 18:11:09 +00:00
case ScriptBaseClass . OBJECT_RUNNING_SCRIPT_COUNT :
2012-04-09 18:58:07 +00:00
ret . Add ( new LSL_Integer ( obj . ParentGroup . RunningScriptCount ( ) ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_TOTAL_SCRIPT_COUNT :
2012-04-09 18:58:07 +00:00
ret . Add ( new LSL_Integer ( obj . ParentGroup . ScriptCount ( ) ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_SCRIPT_MEMORY :
// The value returned in SL for mono scripts is 65536 * number of active scripts
2012-04-09 18:58:07 +00:00
// and 16384 * number of active scripts for LSO. since llGetFreememory
// is coded to give the LSO value use it here
ret . Add ( new LSL_Integer ( obj . ParentGroup . RunningScriptCount ( ) * 16384 ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_SCRIPT_TIME :
2012-04-10 20:25:05 +00:00
// Average cpu time in seconds per simulator frame expended on all scripts in the object
ret . Add ( new LSL_Float ( obj . ParentGroup . ScriptExecutionTime ( ) / 1000.0f ) ) ;
2012-04-06 18:11:09 +00:00
break ;
case ScriptBaseClass . OBJECT_PRIM_EQUIVALENCE :
// according to the SL wiki A prim or linkset will have prim
// equivalent of the number of prims in a linkset if it does not
// contain a mesh anywhere in the link set or is not a normal prim
// The value returned in SL for normal prims is prim count
2012-04-09 18:58:07 +00:00
ret . Add ( new LSL_Integer ( obj . ParentGroup . PrimCount ) ) ;
2012-04-06 18:11:09 +00:00
break ;
2012-04-09 18:58:07 +00:00
// The following 3 costs I have intentionaly coded to return zero. They are part of
// "Land Impact" calculations. These calculations are probably not applicable
// to OpenSim and are not yet complete in SL
2012-04-06 18:11:09 +00:00
case ScriptBaseClass . OBJECT_SERVER_COST :
2012-04-09 18:58:07 +00:00
// The linden calculation is here
// http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
// The value returned in SL for normal prims looks like the prim count
2012-04-06 18:11:09 +00:00
ret . Add ( new LSL_Float ( 0 ) ) ;
break ;
case ScriptBaseClass . OBJECT_STREAMING_COST :
2012-04-09 18:58:07 +00:00
// The linden calculation is here
// http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost
// The value returned in SL for normal prims looks like the prim count * 0.06
2012-04-06 18:11:09 +00:00
ret . Add ( new LSL_Float ( 0 ) ) ;
break ;
case ScriptBaseClass . OBJECT_PHYSICS_COST :
2012-04-09 18:58:07 +00:00
// The linden calculation is here
// http://wiki.secondlife.com/wiki/Mesh/Mesh_physics
// The value returned in SL for normal prims looks like the prim count
2012-04-06 18:11:09 +00:00
ret . Add ( new LSL_Float ( 0 ) ) ;
break ;
default :
// Invalid or unhandled constant.
ret . Add ( new LSL_Integer ( ScriptBaseClass . OBJECT_UNKNOWN_DETAIL ) ) ;
break ;
2008-09-26 02:51:00 +00:00
}
}
2011-07-15 23:08:11 +00:00
2008-09-26 02:51:00 +00:00
return ret ;
}
}
2011-07-15 23:08:11 +00:00
2008-09-26 02:51:00 +00:00
return new LSL_List ( ) ;
}
2012-07-04 20:54:30 +00:00
internal UUID GetScriptByName ( string name )
2008-09-26 02:51:00 +00:00
{
2012-07-04 20:54:30 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( name ) ;
if ( item = = null | | item . Type ! = 10 )
return UUID . Zero ;
2009-07-28 09:40:07 +00:00
2012-07-04 20:54:30 +00:00
return item . ItemID ;
2008-09-26 02:51:00 +00:00
}
internal void ShoutError ( string msg )
{
llShout ( ScriptBaseClass . DEBUG_CHANNEL , msg ) ;
}
internal void NotImplemented ( string command )
{
if ( throwErrorOnNotImplemented )
throw new NotImplementedException ( "Command not implemented: " + command ) ;
}
internal void Deprecated ( string command )
{
throw new Exception ( "Command deprecated: " + command ) ;
}
internal void LSLError ( string msg )
{
throw new Exception ( "LSL Runtime Error: " + msg ) ;
}
public delegate void AssetRequestCallback ( UUID assetID , AssetBase asset ) ;
2009-07-06 13:09:03 +00:00
protected void WithNotecard ( UUID assetID , AssetRequestCallback cb )
2008-09-26 02:51:00 +00:00
{
2009-07-28 09:40:07 +00:00
World . AssetService . Get ( assetID . ToString ( ) , this ,
delegate ( string i , object sender , AssetBase a )
2009-05-15 05:00:25 +00:00
{
UUID uuid = UUID . Zero ;
UUID . TryParse ( i , out uuid ) ;
2009-07-28 09:40:07 +00:00
cb ( uuid , a ) ;
2009-05-15 05:00:25 +00:00
} ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetNumberOfNotecardLines ( string name )
2009-07-28 09:40:07 +00:00
{
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
2009-04-18 19:08:35 +00:00
UUID assetID = UUID . Zero ;
if ( ! UUID . TryParse ( name , out assetID ) )
2008-09-26 02:51:00 +00:00
{
2012-07-04 20:57:57 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( name ) ;
if ( item ! = null & & item . Type = = 7 )
assetID = item . AssetID ;
2008-09-26 02:51:00 +00:00
}
2009-04-18 19:08:35 +00:00
if ( assetID = = UUID . Zero )
{
// => complain loudly, as specified by the LSL docs
ShoutError ( "Notecard '" + name + "' could not be found." ) ;
2009-04-22 01:43:07 +00:00
return UUID . Zero . ToString ( ) ;
2009-04-18 19:08:35 +00:00
}
2009-04-22 09:42:44 +00:00
// was: UUID tid = tid = AsyncCommands.
2012-05-08 22:20:27 +00:00
UUID tid = AsyncCommands . DataserverPlugin . RegisterRequest ( m_host . LocalId , m_item . ItemID , assetID . ToString ( ) ) ;
2009-04-18 19:08:35 +00:00
if ( NotecardCache . IsCached ( assetID ) )
{
AsyncCommands .
DataserverPlugin . DataserverReply ( assetID . ToString ( ) ,
NotecardCache . GetLines ( assetID ) . ToString ( ) ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2009-04-18 19:08:35 +00:00
return tid . ToString ( ) ;
}
2009-07-28 09:40:07 +00:00
2009-04-18 19:08:35 +00:00
WithNotecard ( assetID , delegate ( UUID id , AssetBase a )
{
2009-04-22 01:43:07 +00:00
if ( a = = null | | a . Type ! = 7 )
{
ShoutError ( "Notecard '" + name + "' could not be found." ) ;
2009-04-18 19:08:35 +00:00
return ;
2009-04-22 01:43:07 +00:00
}
2009-04-18 19:08:35 +00:00
2012-07-11 21:54:22 +00:00
string data = Encoding . UTF8 . GetString ( a . Data ) ;
2009-04-18 19:08:35 +00:00
//m_log.Debug(data);
NotecardCache . Cache ( id , data ) ;
AsyncCommands .
DataserverPlugin . DataserverReply ( id . ToString ( ) ,
NotecardCache . GetLines ( id ) . ToString ( ) ) ;
} ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2009-04-22 01:43:07 +00:00
return tid . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
public LSL_String llGetNotecardLine ( string name , int line )
2009-07-28 09:40:07 +00:00
{
2008-09-26 02:51:00 +00:00
m_host . AddScriptLPS ( 1 ) ;
2009-04-18 19:08:35 +00:00
UUID assetID = UUID . Zero ;
if ( ! UUID . TryParse ( name , out assetID ) )
2008-09-26 02:51:00 +00:00
{
2012-07-04 21:00:39 +00:00
TaskInventoryItem item = m_host . Inventory . GetInventoryItem ( name ) ;
if ( item ! = null & & item . Type = = 7 )
assetID = item . AssetID ;
2008-09-26 02:51:00 +00:00
}
2009-04-18 19:08:35 +00:00
if ( assetID = = UUID . Zero )
{
// => complain loudly, as specified by the LSL docs
ShoutError ( "Notecard '" + name + "' could not be found." ) ;
2009-04-22 01:43:07 +00:00
return UUID . Zero . ToString ( ) ;
}
2009-04-18 19:08:35 +00:00
2009-04-22 09:42:44 +00:00
// was: UUID tid = tid = AsyncCommands.
2012-05-08 22:20:27 +00:00
UUID tid = AsyncCommands . DataserverPlugin . RegisterRequest ( m_host . LocalId , m_item . ItemID , assetID . ToString ( ) ) ;
2009-07-28 09:40:07 +00:00
2009-04-18 19:08:35 +00:00
if ( NotecardCache . IsCached ( assetID ) )
{
2009-09-09 06:28:13 +00:00
AsyncCommands . DataserverPlugin . DataserverReply ( assetID . ToString ( ) ,
NotecardCache . GetLine ( assetID , line , m_notecardLineReadCharsMax ) ) ;
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2009-04-18 19:08:35 +00:00
return tid . ToString ( ) ;
}
2009-07-28 09:40:07 +00:00
2009-04-18 19:08:35 +00:00
WithNotecard ( assetID , delegate ( UUID id , AssetBase a )
2009-09-09 06:28:13 +00:00
{
if ( a = = null | | a . Type ! = 7 )
{
ShoutError ( "Notecard '" + name + "' could not be found." ) ;
return ;
}
2012-07-11 21:54:22 +00:00
string data = Encoding . UTF8 . GetString ( a . Data ) ;
2009-09-09 06:28:13 +00:00
//m_log.Debug(data);
NotecardCache . Cache ( id , data ) ;
AsyncCommands . DataserverPlugin . DataserverReply ( id . ToString ( ) ,
NotecardCache . GetLine ( id , line , m_notecardLineReadCharsMax ) ) ;
} ) ;
2009-04-18 19:08:35 +00:00
2009-10-22 04:42:34 +00:00
ScriptSleep ( 100 ) ;
2009-04-22 01:43:07 +00:00
return tid . ToString ( ) ;
2008-09-26 02:51:00 +00:00
}
2010-06-01 23:01:56 +00:00
2012-08-28 02:21:04 +00:00
public void SetPrimitiveParamsEx ( LSL_Key prim , LSL_List rules , string originFunc )
2010-06-01 23:01:56 +00:00
{
SceneObjectPart obj = World . GetSceneObjectPart ( new UUID ( prim ) ) ;
if ( obj = = null )
return ;
2010-06-01 23:04:17 +00:00
if ( obj . OwnerID ! = m_host . OwnerID )
return ;
2012-08-28 02:40:27 +00:00
uint rulesParsed = 0 ;
LSL_List remaining = SetPrimParams ( obj , rules , originFunc , ref rulesParsed ) ;
2012-08-15 20:14:39 +00:00
2012-08-15 21:58:39 +00:00
while ( ( object ) remaining ! = null & & remaining . Length > 2 )
2012-08-15 20:14:39 +00:00
{
LSL_Integer newLink = remaining . GetLSLIntegerItem ( 0 ) ;
LSL_List newrules = remaining . GetSublist ( 1 , - 1 ) ;
foreach ( SceneObjectPart part in GetLinkParts ( obj , newLink ) ) {
2012-08-28 02:40:27 +00:00
remaining = SetPrimParams ( part , newrules , originFunc , ref rulesParsed ) ;
2012-08-15 20:14:39 +00:00
}
}
2010-06-01 23:01:56 +00:00
}
2012-08-24 15:35:59 +00:00
public LSL_List GetPrimitiveParamsEx ( LSL_Key prim , LSL_List rules )
2010-06-01 23:01:56 +00:00
{
SceneObjectPart obj = World . GetSceneObjectPart ( new UUID ( prim ) ) ;
2012-08-24 16:02:13 +00:00
LSL_List result = new LSL_List ( ) ;
2010-06-01 23:04:17 +00:00
2012-08-24 16:02:13 +00:00
if ( obj ! = null & & obj . OwnerID ! = m_host . OwnerID )
{
2012-08-24 16:44:39 +00:00
LSL_List remaining = GetPrimParams ( obj , rules , ref result ) ;
while ( remaining ! = null & & remaining . Length > 2 )
{
int linknumber = remaining . GetLSLIntegerItem ( 0 ) ;
rules = remaining . GetSublist ( 1 , - 1 ) ;
List < SceneObjectPart > parts = GetLinkParts ( linknumber ) ;
foreach ( SceneObjectPart part in parts )
remaining = GetPrimParams ( part , rules , ref result ) ;
}
2012-08-24 16:02:13 +00:00
}
return result ;
2010-06-01 23:01:56 +00:00
}
2011-04-01 04:14:53 +00:00
public void print ( string str )
{
// yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print
2012-05-08 21:58:34 +00:00
IOSSL_Api ossl = ( IOSSL_Api ) m_ScriptEngine . GetApi ( m_item . ItemID , "OSSL" ) ;
2011-04-01 05:56:04 +00:00
if ( ossl ! = null )
{
ossl . CheckThreatLevel ( ThreatLevel . High , "print" ) ;
m_log . Info ( "LSL print():" + str ) ;
}
2011-04-01 04:14:53 +00:00
}
2011-04-08 03:19:17 +00:00
private string Name2Username ( string name )
{
string [ ] parts = name . Split ( new char [ ] { ' ' } ) ;
if ( parts . Length < 2 )
return name . ToLower ( ) ;
if ( parts [ 1 ] = = "Resident" )
return parts [ 0 ] . ToLower ( ) ;
return name . Replace ( " " , "." ) . ToLower ( ) ;
}
public LSL_String llGetUsername ( string id )
{
return Name2Username ( llKey2Name ( id ) ) ;
}
public LSL_String llRequestUsername ( string id )
{
UUID rq = UUID . Random ( ) ;
2012-05-08 22:20:27 +00:00
AsyncCommands . DataserverPlugin . RegisterRequest ( m_host . LocalId , m_item . ItemID , rq . ToString ( ) ) ;
2011-04-08 03:19:17 +00:00
2011-04-11 21:33:24 +00:00
AsyncCommands . DataserverPlugin . DataserverReply ( rq . ToString ( ) , Name2Username ( llKey2Name ( id ) ) ) ;
2011-04-08 03:19:17 +00:00
return rq . ToString ( ) ;
}
public LSL_String llGetDisplayName ( string id )
{
return llKey2Name ( id ) ;
}
public LSL_String llRequestDisplayName ( string id )
{
UUID rq = UUID . Random ( ) ;
2012-05-08 22:20:27 +00:00
AsyncCommands . DataserverPlugin . RegisterRequest ( m_host . LocalId , m_item . ItemID , rq . ToString ( ) ) ;
2011-04-08 03:19:17 +00:00
2011-04-11 21:33:24 +00:00
AsyncCommands . DataserverPlugin . DataserverReply ( rq . ToString ( ) , llKey2Name ( id ) ) ;
2011-04-08 03:19:17 +00:00
return rq . ToString ( ) ;
}
2011-05-22 18:59:18 +00:00
2012-06-13 01:32:25 +00:00
private struct Tri
{
public Vector3 p1 ;
public Vector3 p2 ;
public Vector3 p3 ;
}
private bool InBoundingBox ( ScenePresence avatar , Vector3 point )
{
float height = avatar . Appearance . AvatarHeight ;
Vector3 b1 = avatar . AbsolutePosition + new Vector3 ( - 0.22f , - 0.22f , - height / 2 ) ;
Vector3 b2 = avatar . AbsolutePosition + new Vector3 ( 0.22f , 0.22f , height / 2 ) ;
if ( point . X > b1 . X & & point . X < b2 . X & &
point . Y > b1 . Y & & point . Y < b2 . Y & &
point . Z > b1 . Z & & point . Z < b2 . Z )
return true ;
return false ;
}
private ContactResult [ ] AvatarIntersection ( Vector3 rayStart , Vector3 rayEnd )
{
List < ContactResult > contacts = new List < ContactResult > ( ) ;
Vector3 ab = rayEnd - rayStart ;
World . ForEachScenePresence ( delegate ( ScenePresence sp )
{
Vector3 ac = sp . AbsolutePosition - rayStart ;
Vector3 bc = sp . AbsolutePosition - rayEnd ;
double d = Math . Abs ( Vector3 . Mag ( Vector3 . Cross ( ab , ac ) ) / Vector3 . Distance ( rayStart , rayEnd ) ) ;
if ( d > 1.5 )
return ;
double d2 = Vector3 . Dot ( Vector3 . Negate ( ab ) , ac ) ;
if ( d2 > 0 )
return ;
double dp = Math . Sqrt ( Vector3 . Mag ( ac ) * Vector3 . Mag ( ac ) - d * d ) ;
Vector3 p = rayStart + Vector3 . Divide ( Vector3 . Multiply ( ab , ( float ) dp ) , ( float ) Vector3 . Mag ( ab ) ) ;
if ( ! InBoundingBox ( sp , p ) )
return ;
ContactResult result = new ContactResult ( ) ;
result . ConsumerID = sp . LocalId ;
result . Depth = Vector3 . Distance ( rayStart , p ) ;
result . Normal = Vector3 . Zero ;
result . Pos = p ;
contacts . Add ( result ) ;
} ) ;
return contacts . ToArray ( ) ;
}
private ContactResult [ ] ObjectIntersection ( Vector3 rayStart , Vector3 rayEnd , bool includePhysical , bool includeNonPhysical , bool includePhantom )
{
Ray ray = new Ray ( rayStart , Vector3 . Normalize ( rayEnd - rayStart ) ) ;
List < ContactResult > contacts = new List < ContactResult > ( ) ;
Vector3 ab = rayEnd - rayStart ;
World . ForEachSOG ( delegate ( SceneObjectGroup group )
{
if ( m_host . ParentGroup = = group )
return ;
if ( group . IsAttachment )
return ;
if ( group . RootPart . PhysActor = = null )
{
if ( ! includePhantom )
return ;
}
else
{
if ( group . RootPart . PhysActor . IsPhysical )
{
if ( ! includePhysical )
return ;
}
else
{
if ( ! includeNonPhysical )
return ;
}
}
// Find the radius ouside of which we don't even need to hit test
float minX ;
float maxX ;
float minY ;
float maxY ;
float minZ ;
float maxZ ;
float radius = 0.0f ;
group . GetAxisAlignedBoundingBoxRaw ( out minX , out maxX , out minY , out maxY , out minZ , out maxZ ) ;
if ( Math . Abs ( minX ) > radius )
radius = Math . Abs ( minX ) ;
if ( Math . Abs ( minY ) > radius )
radius = Math . Abs ( minY ) ;
if ( Math . Abs ( minZ ) > radius )
radius = Math . Abs ( minZ ) ;
if ( Math . Abs ( maxX ) > radius )
radius = Math . Abs ( maxX ) ;
if ( Math . Abs ( maxY ) > radius )
radius = Math . Abs ( maxY ) ;
if ( Math . Abs ( maxZ ) > radius )
radius = Math . Abs ( maxZ ) ;
Vector3 ac = group . AbsolutePosition - rayStart ;
Vector3 bc = group . AbsolutePosition - rayEnd ;
double d = Math . Abs ( Vector3 . Mag ( Vector3 . Cross ( ab , ac ) ) / Vector3 . Distance ( rayStart , rayEnd ) ) ;
// Too far off ray, don't bother
if ( d > radius )
return ;
// Behind ray, drop
double d2 = Vector3 . Dot ( Vector3 . Negate ( ab ) , ac ) ;
if ( d2 > 0 )
return ;
EntityIntersection intersection = group . TestIntersection ( ray , true , false ) ;
// Miss.
if ( ! intersection . HitTF )
return ;
ContactResult result = new ContactResult ( ) ;
result . ConsumerID = group . LocalId ;
result . Depth = intersection . distance ;
result . Normal = intersection . normal ;
result . Pos = intersection . ipoint ;
contacts . Add ( result ) ;
} ) ;
return contacts . ToArray ( ) ;
}
private ContactResult ? GroundIntersection ( Vector3 rayStart , Vector3 rayEnd )
{
double [ , ] heightfield = World . Heightmap . GetDoubles ( ) ;
List < ContactResult > contacts = new List < ContactResult > ( ) ;
double min = 2048.0 ;
double max = 0.0 ;
// Find the min and max of the heightfield
for ( int x = 0 ; x < World . Heightmap . Width ; x + + )
{
for ( int y = 0 ; y < World . Heightmap . Height ; y + + )
{
if ( heightfield [ x , y ] > max )
max = heightfield [ x , y ] ;
if ( heightfield [ x , y ] < min )
min = heightfield [ x , y ] ;
}
}
// A ray extends past rayEnd, but doesn't go back before
// rayStart. If the start is above the highest point of the ground
// and the ray goes up, we can't hit the ground. Ever.
if ( rayStart . Z > max & & rayEnd . Z > = rayStart . Z )
return null ;
// Same for going down
if ( rayStart . Z < min & & rayEnd . Z < = rayStart . Z )
return null ;
List < Tri > trilist = new List < Tri > ( ) ;
// Create our triangle list
for ( int x = 1 ; x < World . Heightmap . Width ; x + + )
{
for ( int y = 1 ; y < World . Heightmap . Height ; y + + )
{
Tri t1 = new Tri ( ) ;
Tri t2 = new Tri ( ) ;
Vector3 p1 = new Vector3 ( x - 1 , y - 1 , ( float ) heightfield [ x - 1 , y - 1 ] ) ;
Vector3 p2 = new Vector3 ( x , y - 1 , ( float ) heightfield [ x , y - 1 ] ) ;
Vector3 p3 = new Vector3 ( x , y , ( float ) heightfield [ x , y ] ) ;
Vector3 p4 = new Vector3 ( x - 1 , y , ( float ) heightfield [ x - 1 , y ] ) ;
t1 . p1 = p1 ;
t1 . p2 = p2 ;
t1 . p3 = p3 ;
t2 . p1 = p3 ;
t2 . p2 = p4 ;
t2 . p3 = p1 ;
trilist . Add ( t1 ) ;
trilist . Add ( t2 ) ;
}
}
// Ray direction
Vector3 rayDirection = rayEnd - rayStart ;
foreach ( Tri t in trilist )
{
// Compute triangle plane normal and edges
Vector3 u = t . p2 - t . p1 ;
Vector3 v = t . p3 - t . p1 ;
Vector3 n = Vector3 . Cross ( u , v ) ;
if ( n = = Vector3 . Zero )
continue ;
Vector3 w0 = rayStart - t . p1 ;
double a = - Vector3 . Dot ( n , w0 ) ;
double b = Vector3 . Dot ( n , rayDirection ) ;
// Not intersecting the plane, or in plane (same thing)
// Ignoring this MAY cause the ground to not be detected
// sometimes
if ( Math . Abs ( b ) < 0.000001 )
continue ;
double r = a / b ;
// ray points away from plane
if ( r < 0.0 )
continue ;
Vector3 ip = rayStart + Vector3 . Multiply ( rayDirection , ( float ) r ) ;
float uu = Vector3 . Dot ( u , u ) ;
float uv = Vector3 . Dot ( u , v ) ;
float vv = Vector3 . Dot ( v , v ) ;
Vector3 w = ip - t . p1 ;
float wu = Vector3 . Dot ( w , u ) ;
float wv = Vector3 . Dot ( w , v ) ;
float d = uv * uv - uu * vv ;
float cs = ( uv * wv - vv * wu ) / d ;
if ( cs < 0 | | cs > 1.0 )
continue ;
float ct = ( uv * wu - uu * wv ) / d ;
if ( ct < 0 | | ( cs + ct ) > 1.0 )
continue ;
// Add contact point
ContactResult result = new ContactResult ( ) ;
result . ConsumerID = 0 ;
result . Depth = Vector3 . Distance ( rayStart , ip ) ;
result . Normal = n ;
result . Pos = ip ;
contacts . Add ( result ) ;
}
if ( contacts . Count = = 0 )
return null ;
contacts . Sort ( delegate ( ContactResult a , ContactResult b )
{
return ( int ) ( a . Depth - b . Depth ) ;
} ) ;
return contacts [ 0 ] ;
}
2011-07-12 21:13:15 +00:00
public LSL_List llCastRay ( LSL_Vector start , LSL_Vector end , LSL_List options )
{
2012-06-13 01:32:25 +00:00
LSL_List list = new LSL_List ( ) ;
2011-07-12 21:13:15 +00:00
m_host . AddScriptLPS ( 1 ) ;
2012-08-18 00:17:01 +00:00
Vector3 rayStart = start ;
Vector3 rayEnd = end ;
2012-06-13 01:32:25 +00:00
Vector3 dir = rayEnd - rayStart ;
2011-07-12 21:13:15 +00:00
2012-06-13 01:32:25 +00:00
float dist = Vector3 . Mag ( dir ) ;
int count = 1 ;
bool detectPhantom = false ;
2011-07-12 21:13:15 +00:00
int dataFlags = 0 ;
int rejectTypes = 0 ;
for ( int i = 0 ; i < options . Length ; i + = 2 )
{
if ( options . GetLSLIntegerItem ( i ) = = ScriptBaseClass . RC_MAX_HITS )
count = options . GetLSLIntegerItem ( i + 1 ) ;
2012-06-13 01:32:25 +00:00
else if ( options . GetLSLIntegerItem ( i ) = = ScriptBaseClass . RC_DETECT_PHANTOM )
detectPhantom = ( options . GetLSLIntegerItem ( i + 1 ) > 0 ) ;
2011-07-12 21:13:15 +00:00
else if ( options . GetLSLIntegerItem ( i ) = = ScriptBaseClass . RC_DATA_FLAGS )
dataFlags = options . GetLSLIntegerItem ( i + 1 ) ;
else if ( options . GetLSLIntegerItem ( i ) = = ScriptBaseClass . RC_REJECT_TYPES )
rejectTypes = options . GetLSLIntegerItem ( i + 1 ) ;
}
2012-06-13 01:32:25 +00:00
if ( count > 16 )
count = 16 ;
2011-07-12 21:13:15 +00:00
2012-06-13 01:32:25 +00:00
List < ContactResult > results = new List < ContactResult > ( ) ;
2011-07-12 21:13:15 +00:00
bool checkTerrain = ! ( ( rejectTypes & ScriptBaseClass . RC_REJECT_LAND ) = = ScriptBaseClass . RC_REJECT_LAND ) ;
bool checkAgents = ! ( ( rejectTypes & ScriptBaseClass . RC_REJECT_AGENTS ) = = ScriptBaseClass . RC_REJECT_AGENTS ) ;
bool checkNonPhysical = ! ( ( rejectTypes & ScriptBaseClass . RC_REJECT_NONPHYSICAL ) = = ScriptBaseClass . RC_REJECT_NONPHYSICAL ) ;
bool checkPhysical = ! ( ( rejectTypes & ScriptBaseClass . RC_REJECT_PHYSICAL ) = = ScriptBaseClass . RC_REJECT_PHYSICAL ) ;
2012-06-13 01:32:25 +00:00
if ( checkTerrain )
2011-07-12 21:13:15 +00:00
{
2012-06-13 01:32:25 +00:00
ContactResult ? groundContact = GroundIntersection ( rayStart , rayEnd ) ;
if ( groundContact ! = null )
results . Add ( ( ContactResult ) groundContact ) ;
}
2011-07-12 21:13:15 +00:00
2012-06-13 01:32:25 +00:00
if ( checkAgents )
{
ContactResult [ ] agentHits = AvatarIntersection ( rayStart , rayEnd ) ;
foreach ( ContactResult r in agentHits )
results . Add ( r ) ;
}
2011-07-12 21:13:15 +00:00
2012-06-13 01:32:25 +00:00
if ( checkPhysical | | checkNonPhysical | | detectPhantom )
{
ContactResult [ ] objectHits = ObjectIntersection ( rayStart , rayEnd , checkPhysical , checkNonPhysical , detectPhantom ) ;
foreach ( ContactResult r in objectHits )
results . Add ( r ) ;
2011-07-12 21:13:15 +00:00
}
2012-06-13 01:32:25 +00:00
results . Sort ( delegate ( ContactResult a , ContactResult b )
{
return a . Depth . CompareTo ( b . Depth ) ;
} ) ;
int values = 0 ;
SceneObjectGroup thisgrp = m_host . ParentGroup ;
2011-07-12 21:13:15 +00:00
foreach ( ContactResult result in results )
{
2012-06-13 01:32:25 +00:00
if ( result . Depth > dist )
2011-07-12 21:13:15 +00:00
continue ;
2012-06-13 01:32:25 +00:00
// physics ray can return colisions with host prim
if ( m_host . LocalId = = result . ConsumerID )
continue ;
2011-07-12 21:13:15 +00:00
2012-06-13 01:32:25 +00:00
UUID itemID = UUID . Zero ;
int linkNum = 0 ;
2011-07-12 21:13:15 +00:00
2012-06-13 01:32:25 +00:00
SceneObjectPart part = World . GetSceneObjectPart ( result . ConsumerID ) ;
// It's a prim!
if ( part ! = null )
2011-07-12 21:13:15 +00:00
{
2012-06-13 01:32:25 +00:00
// dont detect members of same object ???
if ( part . ParentGroup = = thisgrp )
continue ;
2011-07-12 21:13:15 +00:00
2012-06-13 01:32:25 +00:00
if ( ( dataFlags & ScriptBaseClass . RC_GET_ROOT_KEY ) = = ScriptBaseClass . RC_GET_ROOT_KEY )
itemID = part . ParentGroup . UUID ;
else
itemID = part . UUID ;
2011-07-12 21:13:15 +00:00
2012-06-13 01:32:25 +00:00
linkNum = part . LinkNum ;
2011-07-12 21:13:15 +00:00
}
2012-06-13 01:32:25 +00:00
else
2011-07-12 21:13:15 +00:00
{
2012-06-13 01:32:25 +00:00
ScenePresence sp = World . GetScenePresence ( result . ConsumerID ) ;
/// It it a boy? a girl?
if ( sp ! = null )
itemID = sp . UUID ;
2011-07-12 21:13:15 +00:00
}
2012-06-13 01:32:25 +00:00
list . Add ( new LSL_String ( itemID . ToString ( ) ) ) ;
list . Add ( new LSL_String ( result . Pos . ToString ( ) ) ) ;
2011-07-12 21:13:15 +00:00
if ( ( dataFlags & ScriptBaseClass . RC_GET_LINK_NUM ) = = ScriptBaseClass . RC_GET_LINK_NUM )
2012-06-13 01:32:25 +00:00
list . Add ( new LSL_Integer ( linkNum ) ) ;
2011-07-12 21:13:15 +00:00
if ( ( dataFlags & ScriptBaseClass . RC_GET_NORMAL ) = = ScriptBaseClass . RC_GET_NORMAL )
2012-06-13 01:32:25 +00:00
list . Add ( new LSL_Vector ( result . Normal . X , result . Normal . Y , result . Normal . Z ) ) ;
values + + ;
if ( values > = count )
break ;
2011-07-12 21:13:15 +00:00
}
2012-06-13 01:32:25 +00:00
list . Add ( new LSL_Integer ( values ) ) ;
2011-07-12 21:13:15 +00:00
return list ;
}
2012-01-26 20:53:42 +00:00
public LSL_Integer llManageEstateAccess ( int action , string avatar )
{
m_host . AddScriptLPS ( 1 ) ;
EstateSettings estate = World . RegionInfo . EstateSettings ;
bool isAccount = false ;
bool isGroup = false ;
2012-04-17 00:25:41 +00:00
if ( ! estate . IsEstateOwner ( m_host . OwnerID ) | | ! estate . IsEstateManagerOrOwner ( m_host . OwnerID ) )
2012-01-26 20:53:42 +00:00
return 0 ;
UUID id = new UUID ( ) ;
if ( ! UUID . TryParse ( avatar , out id ) )
return 0 ;
UserAccount account = World . UserAccountService . GetUserAccount ( World . RegionInfo . ScopeID , id ) ;
isAccount = account ! = null ? true : false ;
if ( ! isAccount )
{
IGroupsModule groups = World . RequestModuleInterface < IGroupsModule > ( ) ;
if ( groups ! = null )
{
GroupRecord group = groups . GetGroupRecord ( id ) ;
isGroup = group ! = null ? true : false ;
if ( ! isGroup )
return 0 ;
}
else
return 0 ;
}
switch ( action )
{
case ScriptBaseClass . ESTATE_ACCESS_ALLOWED_AGENT_ADD :
if ( ! isAccount ) return 0 ;
if ( estate . HasAccess ( id ) ) return 1 ;
if ( estate . IsBanned ( id ) )
estate . RemoveBan ( id ) ;
estate . AddEstateUser ( id ) ;
break ;
case ScriptBaseClass . ESTATE_ACCESS_ALLOWED_AGENT_REMOVE :
if ( ! isAccount | | ! estate . HasAccess ( id ) ) return 0 ;
estate . RemoveEstateUser ( id ) ;
break ;
case ScriptBaseClass . ESTATE_ACCESS_ALLOWED_GROUP_ADD :
if ( ! isGroup ) return 0 ;
if ( estate . GroupAccess ( id ) ) return 1 ;
estate . AddEstateGroup ( id ) ;
break ;
case ScriptBaseClass . ESTATE_ACCESS_ALLOWED_GROUP_REMOVE :
if ( ! isGroup | | ! estate . GroupAccess ( id ) ) return 0 ;
estate . RemoveEstateGroup ( id ) ;
break ;
case ScriptBaseClass . ESTATE_ACCESS_BANNED_AGENT_ADD :
if ( ! isAccount ) return 0 ;
if ( estate . IsBanned ( id ) ) return 1 ;
EstateBan ban = new EstateBan ( ) ;
ban . EstateID = estate . EstateID ;
ban . BannedUserID = id ;
estate . AddBan ( ban ) ;
break ;
case ScriptBaseClass . ESTATE_ACCESS_BANNED_AGENT_REMOVE :
if ( ! isAccount | | ! estate . IsBanned ( id ) ) return 0 ;
estate . RemoveBan ( id ) ;
break ;
default : return 0 ;
}
return 1 ;
}
2012-04-13 23:37:55 +00:00
public LSL_Integer llGetMemoryLimit ( )
{
m_host . AddScriptLPS ( 1 ) ;
// The value returned for LSO scripts in SL
return 16384 ;
}
2011-05-22 18:59:18 +00:00
2012-04-13 23:37:55 +00:00
public LSL_Integer llSetMemoryLimit ( LSL_Integer limit )
2011-05-22 18:59:18 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2012-04-13 23:37:55 +00:00
// Treat as an LSO script
return ScriptBaseClass . FALSE ;
2011-05-22 18:59:18 +00:00
}
2012-04-13 23:37:55 +00:00
public LSL_Integer llGetSPMaxMemory ( )
2011-05-22 18:59:18 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2012-04-13 23:37:55 +00:00
// The value returned for LSO scripts in SL
return 16384 ;
2011-05-22 18:59:18 +00:00
}
2012-04-13 23:37:55 +00:00
public LSL_Integer llGetUsedMemory ( )
2011-05-22 18:59:18 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2012-04-13 23:37:55 +00:00
// The value returned for LSO scripts in SL
return 16384 ;
2011-05-22 18:59:18 +00:00
}
2011-07-12 21:13:15 +00:00
public void llScriptProfiler ( LSL_Integer flags )
2011-05-22 18:59:18 +00:00
{
m_host . AddScriptLPS ( 1 ) ;
2012-04-13 23:37:55 +00:00
// This does nothing for LSO scripts in SL
}
#region Not Implemented
/ /
// Listing the unimplemented lsl functions here, please move
// them from this region as they are completed
/ /
public void llGetEnv ( LSL_String name )
{
m_host . AddScriptLPS ( 1 ) ;
NotImplemented ( "llGetEnv" ) ;
2011-05-22 18:59:18 +00:00
}
public void llSetSoundQueueing ( int queue )
{
m_host . AddScriptLPS ( 1 ) ;
NotImplemented ( "llSetSoundQueueing" ) ;
}
public void llCollisionSprite ( string impact_sprite )
{
m_host . AddScriptLPS ( 1 ) ;
NotImplemented ( "llCollisionSprite" ) ;
}
public void llGodLikeRezObject ( string inventory , LSL_Vector pos )
{
m_host . AddScriptLPS ( 1 ) ;
NotImplemented ( "llGodLikeRezObject" ) ;
}
# endregion
2008-09-26 02:51:00 +00:00
}
public class NotecardCache
{
2009-07-06 13:09:03 +00:00
protected class Notecard
2008-09-26 02:51:00 +00:00
{
public string [ ] text ;
public DateTime lastRef ;
}
2009-07-06 13:09:03 +00:00
protected static Dictionary < UUID , Notecard > m_Notecards =
2009-07-28 09:40:07 +00:00
new Dictionary < UUID , Notecard > ( ) ;
2008-09-26 02:51:00 +00:00
public static void Cache ( UUID assetID , string text )
{
CacheCheck ( ) ;
lock ( m_Notecards )
{
if ( m_Notecards . ContainsKey ( assetID ) )
return ;
Notecard nc = new Notecard ( ) ;
nc . lastRef = DateTime . Now ;
2010-03-04 20:08:25 +00:00
nc . text = SLUtil . ParseNotecardToList ( text ) . ToArray ( ) ;
2008-09-26 02:51:00 +00:00
m_Notecards [ assetID ] = nc ;
}
}
public static bool IsCached ( UUID assetID )
{
lock ( m_Notecards )
{
return m_Notecards . ContainsKey ( assetID ) ;
}
}
public static int GetLines ( UUID assetID )
{
if ( ! IsCached ( assetID ) )
return - 1 ;
lock ( m_Notecards )
{
m_Notecards [ assetID ] . lastRef = DateTime . Now ;
return m_Notecards [ assetID ] . text . Length ;
}
}
2011-08-09 02:51:34 +00:00
/// <summary>
/// Get a notecard line.
/// </summary>
/// <param name="assetID"></param>
/// <param name="line">Lines start at index 0</param>
/// <returns></returns>
public static string GetLine ( UUID assetID , int lineNumber )
2008-09-26 02:51:00 +00:00
{
2011-08-09 02:51:34 +00:00
if ( lineNumber < 0 )
2008-09-26 02:51:00 +00:00
return "" ;
string data ;
if ( ! IsCached ( assetID ) )
return "" ;
lock ( m_Notecards )
{
m_Notecards [ assetID ] . lastRef = DateTime . Now ;
2011-08-09 02:51:34 +00:00
if ( lineNumber > = m_Notecards [ assetID ] . text . Length )
2008-09-26 02:51:00 +00:00
return "\n\n\n" ;
2011-08-09 02:51:34 +00:00
data = m_Notecards [ assetID ] . text [ lineNumber ] ;
2008-09-26 02:51:00 +00:00
return data ;
}
}
2011-08-09 02:51:34 +00:00
/// <summary>
/// Get a notecard line.
/// </summary>
/// <param name="assetID"></param>
/// <param name="line">Lines start at index 0</param>
/// <param name="maxLength">Maximum length of the returned line. Longer lines will be truncated</para>
/// <returns></returns>
public static string GetLine ( UUID assetID , int lineNumber , int maxLength )
{
string line = GetLine ( assetID , lineNumber ) ;
if ( line . Length > maxLength )
line = line . Substring ( 0 , maxLength ) ;
return line ;
}
2008-09-26 02:51:00 +00:00
public static void CacheCheck ( )
{
foreach ( UUID key in new List < UUID > ( m_Notecards . Keys ) )
{
Notecard nc = m_Notecards [ key ] ;
if ( nc . lastRef . AddSeconds ( 30 ) < DateTime . Now )
m_Notecards . Remove ( key ) ;
2008-05-30 12:27:06 +00:00
}
}
}
2010-03-07 16:05:24 +00:00
}