diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs index 4cd587cb71..2405d4a6bf 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs @@ -55,4 +55,4 @@ using System.Runtime.InteropServices; // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): -[assembly : AssemblyVersion("1.0.*")] \ No newline at end of file +[assembly : AssemblyVersion("1.0.*")] diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs index d7d91bebcd..64118870de 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs @@ -1,336 +1,365 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -using System.Collections.Generic; -using Axiom.Math; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BasicPhysicsPlugin -{ - /// - /// Will be the PhysX plugin but for now will be a very basic physics engine - /// - public class BasicPhysicsPlugin : IPhysicsPlugin - { - public BasicPhysicsPlugin() - { - } - - public bool Init() - { - return true; - } - - public PhysicsScene GetScene() - { - return new BasicScene(); - } - - public string GetName() - { - return ("basicphysics"); - } - - public void Dispose() - { - } - } - - public class BasicScene : PhysicsScene - { - private List _actors = new List(); - private float[] _heightMap; - - public BasicScene() - { - } - - public override void Initialise(IMesher meshmerizer) - { - // Does nothing right now - } - - public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID) - { - BasicActor act = new BasicActor(); - act.Position = position; - _actors.Add(act); - return act; - } - - public override void RemovePrim(PhysicsActor prim) - { - } - - public override void RemoveAvatar(PhysicsActor actor) - { - BasicActor act = (BasicActor) actor; - if (_actors.Contains(act)) - { - _actors.Remove(act); - } - } - -/* - public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) - { - return null; - } -*/ - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, uint LocalID) - { - return AddPrimShape(primName, pbs, position, size, rotation, false, LocalID); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) // rex, modified - { - return null; - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - float fps = 0; - for (int i = 0; i < _actors.Count; ++i) - { - BasicActor actor = _actors[i]; - - actor.Position.X += actor.Velocity.X*timeStep; - actor.Position.Y += actor.Velocity.Y*timeStep; - - if (actor.Position.Y < 0) - { - actor.Position.Y = 0.1F; - } - else if (actor.Position.Y >= 256) - { - actor.Position.Y = 255.9F; - } - - if (actor.Position.X < 0) - { - actor.Position.X = 0.1F; - } - else if (actor.Position.X >= 256) - { - actor.Position.X = 255.9F; - } - - float height = _heightMap[(int) actor.Position.Y*256 + (int) actor.Position.X] + 1.0f; - if (actor.Flying) - { - if (actor.Position.Z + (actor.Velocity.Z*timeStep) < - _heightMap[(int) actor.Position.Y*256 + (int) actor.Position.X] + 2) - { - actor.Position.Z = height; - actor.Velocity.Z = 0; - } - else - { - actor.Position.Z += actor.Velocity.Z*timeStep; - } - } - else - { - actor.Position.Z = height; - actor.Velocity.Z = 0; - } - } - return fps; - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - get { return (false); // for now we won't be multithreaded - } - } - - public override void SetTerrain(float[] heightMap) - { - _heightMap = heightMap; - } - - public override void DeleteTerrain() - { - } - } - - public class BasicActor : PhysicsActor - { - private PhysicsVector _position; - private PhysicsVector _velocity; - private PhysicsVector _acceleration; - private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; - private bool flying; - private bool iscolliding; - - public BasicActor() - { - _velocity = new PhysicsVector(); - _position = new PhysicsVector(); - _acceleration = new PhysicsVector(); - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override PhysicsVector RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool Flying - { - get { return flying; } - set { flying = value; } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override PhysicsVector Position - { - get { return _position; } - set { _position = value; } - } - - public override PhysicsVector Size - { - get { return PhysicsVector.Zero; } - set { } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override float Mass - { - get { return 0f; } - } - - public override PhysicsVector Force - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector Velocity - { - get { return _velocity; } - set { _velocity = value; } - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - public override bool Kinematic - { - get { return true; } - set { } - } - - public void SetAcceleration(PhysicsVector accel) - { - _acceleration = accel; - } - - public override void AddForce(PhysicsVector force) - { - } - - public override void SetMomentum(PhysicsVector momentum) - { - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System.Collections.Generic; +using Axiom.Math; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.BasicPhysicsPlugin +{ + /// + /// Will be the PhysX plugin but for now will be a very basic physics engine + /// + public class BasicPhysicsPlugin : IPhysicsPlugin + { + public BasicPhysicsPlugin() + { + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + return new BasicScene(); + } + + public string GetName() + { + return ("basicphysics"); + } + + public void Dispose() + { + } + } + + public class BasicScene : PhysicsScene + { + private List _actors = new List(); + private float[] _heightMap; + + public BasicScene() + { + } + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID) + { + + } + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + BasicActor act = new BasicActor(); + act.Position = position; + _actors.Add(act); + return act; + } + + public override void RemovePrim(PhysicsActor prim) + { + } + + public override void RemoveAvatar(PhysicsActor actor) + { + BasicActor act = (BasicActor) actor; + if (_actors.Contains(act)) + { + _actors.Remove(act); + } + } + +/* + public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) + { + return null; + } +*/ + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, uint LocalID) + { + return AddPrimShape(primName, pbs, position, size, rotation, false, LocalID); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) // rex, modified + { + return null; + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + float fps = 0; + for (int i = 0; i < _actors.Count; ++i) + { + BasicActor actor = _actors[i]; + + actor.Position.X += actor.Velocity.X*timeStep; + actor.Position.Y += actor.Velocity.Y*timeStep; + + if (actor.Position.Y < 0) + { + actor.Position.Y = 0.1F; + } + else if (actor.Position.Y >= Constants.RegionSize) + { + actor.Position.Y = 255.9F; + } + + if (actor.Position.X < 0) + { + actor.Position.X = 0.1F; + } + else if (actor.Position.X >= Constants.RegionSize) + { + actor.Position.X = 255.9F; + } + + float height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 1.0f; + if (actor.Flying) + { + if (actor.Position.Z + (actor.Velocity.Z*timeStep) < + _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 2) + { + actor.Position.Z = height; + actor.Velocity.Z = 0; + } + else + { + actor.Position.Z += actor.Velocity.Z*timeStep; + } + } + else + { + actor.Position.Z = height; + actor.Velocity.Z = 0; + } + } + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + get { return (false); // for now we won't be multithreaded + } + } + + public override void SetTerrain(float[] heightMap) + { + _heightMap = heightMap; + } + + public override void DeleteTerrain() + { + } + } + + public class BasicActor : PhysicsActor + { + private PhysicsVector _position; + private PhysicsVector _velocity; + private PhysicsVector _acceleration; + private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + private bool flying; + private bool iscolliding; + + public BasicActor() + { + _velocity = new PhysicsVector(); + _position = new PhysicsVector(); + _acceleration = new PhysicsVector(); + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Stopped + { + get { return false; } + } + + + public override PhysicsVector Position + { + get { return _position; } + set { _position = value; } + } + + public override PhysicsVector Size + { + get { return PhysicsVector.Zero; } + set { } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public override bool Kinematic + { + get { return true; } + set { } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + public override void CrossingFailure() + { + + } + } +} diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs index f6d0f6a9da..7d5d6d0023 100644 --- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs +++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs @@ -1,1531 +1,1558 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -#region Copyright - -/* -* Copyright (c) Contributors, http://www.openmetaverse.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -#endregion - -#region References - -using System; -using System.Collections.Generic; -using MonoXnaCompactMaths; -using OpenSim.Framework; -using OpenSim.Framework.Console; -using OpenSim.Region.Physics.Manager; -using XnaDevRu.BulletX; -using XnaDevRu.BulletX.Dynamics; -using AxiomQuaternion = Axiom.Math.Quaternion; -using BoxShape=XnaDevRu.BulletX.BoxShape; - -#endregion - -namespace OpenSim.Region.Physics.BulletXPlugin -{ - /// - /// BulletXConversions are called now BulletXMaths - /// This Class converts objects and types for BulletX and give some operations - /// - public class BulletXMaths - { - //Vector3 - public static Vector3 PhysicsVectorToXnaVector3(PhysicsVector physicsVector) - { - return new Vector3(physicsVector.X, physicsVector.Y, physicsVector.Z); - } - - public static PhysicsVector XnaVector3ToPhysicsVector(Vector3 xnaVector3) - { - return new PhysicsVector(xnaVector3.X, xnaVector3.Y, xnaVector3.Z); - } - - //Quaternion - public static Quaternion AxiomQuaternionToXnaQuaternion(AxiomQuaternion axiomQuaternion) - { - return new Quaternion(axiomQuaternion.x, axiomQuaternion.y, axiomQuaternion.z, axiomQuaternion.w); - } - - public static AxiomQuaternion XnaQuaternionToAxiomQuaternion(Quaternion xnaQuaternion) - { - return new AxiomQuaternion(xnaQuaternion.W, xnaQuaternion.X, xnaQuaternion.Y, xnaQuaternion.Z); - } - - //Next methods are extracted from XnaDevRu.BulletX(See 3rd party license): - //- SetRotation (class MatrixOperations) - //- GetRotation (class MatrixOperations) - //- GetElement (class MathHelper) - //- SetElement (class MathHelper) - internal static void SetRotation(ref Matrix m, Quaternion q) - { - float d = q.LengthSquared(); - float s = 2f/d; - float xs = q.X*s, ys = q.Y*s, zs = q.Z*s; - float wx = q.W*xs, wy = q.W*ys, wz = q.W*zs; - float xx = q.X*xs, xy = q.X*ys, xz = q.X*zs; - float yy = q.Y*ys, yz = q.Y*zs, zz = q.Z*zs; - m = new Matrix(1 - (yy + zz), xy - wz, xz + wy, 0, - xy + wz, 1 - (xx + zz), yz - wx, 0, - xz - wy, yz + wx, 1 - (xx + yy), 0, - m.M41, m.M42, m.M43, 1); - } - - internal static Quaternion GetRotation(Matrix m) - { - Quaternion q = new Quaternion(); - - float trace = m.M11 + m.M22 + m.M33; - - if (trace > 0) - { - float s = (float) Math.Sqrt(trace + 1); - q.W = s*0.5f; - s = 0.5f/s; - - q.X = (m.M32 - m.M23)*s; - q.Y = (m.M13 - m.M31)*s; - q.Z = (m.M21 - m.M12)*s; - } - else - { - int i = m.M11 < m.M22 - ? - (m.M22 < m.M33 ? 2 : 1) - : - (m.M11 < m.M33 ? 2 : 0); - int j = (i + 1)%3; - int k = (i + 2)%3; - - float s = (float) Math.Sqrt(GetElement(m, i, i) - GetElement(m, j, j) - GetElement(m, k, k) + 1); - SetElement(ref q, i, s*0.5f); - s = 0.5f/s; - - q.W = (GetElement(m, k, j) - GetElement(m, j, k))*s; - SetElement(ref q, j, (GetElement(m, j, i) + GetElement(m, i, j))*s); - SetElement(ref q, k, (GetElement(m, k, i) + GetElement(m, i, k))*s); - } - - return q; - } - - internal static float SetElement(ref Quaternion q, int index, float value) - { - switch (index) - { - case 0: - q.X = value; - break; - case 1: - q.Y = value; - break; - case 2: - q.Z = value; - break; - case 3: - q.W = value; - break; - } - - return 0; - } - - internal static float GetElement(Matrix mat, int row, int col) - { - switch (row) - { - case 0: - switch (col) - { - case 0: - return mat.M11; - case 1: - return mat.M12; - case 2: - return mat.M13; - } - break; - case 1: - switch (col) - { - case 0: - return mat.M21; - case 1: - return mat.M22; - case 2: - return mat.M23; - } - break; - case 2: - switch (col) - { - case 0: - return mat.M31; - case 1: - return mat.M32; - case 2: - return mat.M33; - } - break; - } - - return 0; - } - } - - /// - /// PhysicsPlugin Class for BulletX - /// - public class BulletXPlugin : IPhysicsPlugin - { - private BulletXScene _mScene; - - public BulletXPlugin() - { - } - - public bool Init() - { - return true; - } - - public PhysicsScene GetScene() - { - if (_mScene == null) - { - _mScene = new BulletXScene(); - } - return (_mScene); - } - - public string GetName() - { - return ("modified_BulletX"); //Changed!! "BulletXEngine" To "modified_BulletX" - } - - public void Dispose() - { - } - } - - - // Class to detect and debug collisions - // Mainly used for debugging purposes - internal class CollisionDispatcherLocal : CollisionDispatcher - { - private BulletXScene relatedScene; - - public CollisionDispatcherLocal(BulletXScene s) - : base() - { - relatedScene = s; - } - - public override bool NeedsCollision(CollisionObject bodyA, CollisionObject bodyB) - { - RigidBody rb; - BulletXCharacter bxcA = null; - BulletXPrim bxpA = null; - Type t = bodyA.GetType(); - if (t == typeof (RigidBody)) - { - rb = (RigidBody) bodyA; - relatedScene._characters.TryGetValue(rb, out bxcA); - relatedScene._prims.TryGetValue(rb, out bxpA); - } - String nameA; - if (bxcA != null) - nameA = bxcA._name; - else if (bxpA != null) - nameA = bxpA._name; - else - nameA = "null"; - - BulletXCharacter bxcB = null; - BulletXPrim bxpB = null; - t = bodyB.GetType(); - if (t == typeof (RigidBody)) - { - rb = (RigidBody) bodyB; - relatedScene._characters.TryGetValue(rb, out bxcB); - relatedScene._prims.TryGetValue(rb, out bxpB); - } - String nameB; - if (bxcB != null) - nameB = bxcB._name; - else if (bxpB != null) - nameB = bxpB._name; - else - nameB = "null"; - - bool needsCollision = base.NeedsCollision(bodyA, bodyB); - - MainLog.Instance.Debug("BulletX", "A collision was detected between {0} and {1} --> {2}", nameA, nameB, - needsCollision); - - - return needsCollision; - } - } - - /// - /// PhysicsScene Class for BulletX - /// - public class BulletXScene : PhysicsScene - { - #region BulletXScene Fields - - public DiscreteDynamicsWorld ddWorld; - private CollisionDispatcher cDispatcher; - private OverlappingPairCache opCache; - private SequentialImpulseConstraintSolver sicSolver; - public static Object BulletXLock = new Object(); - - private const int minXY = 0; - private const int minZ = 0; - private const int maxXY = 256; - private const int maxZ = 4096; - private const int maxHandles = 32766; //Why? I don't know - private const float gravity = 9.8f; - private const float heightLevel0 = 77.0f; - private const float heightLevel1 = 200.0f; - private const float lowGravityFactor = 0.2f; - //OpenSim calls Simulate 10 times per seconds. So FPS = "Simulate Calls" * simulationSubSteps = 100 FPS - private const int simulationSubSteps = 10; - //private float[] _heightmap; - private BulletXPlanet _simFlatPlanet; - internal Dictionary _characters = new Dictionary(); - internal Dictionary _prims = new Dictionary(); - - public IMesher mesher; - - - public static float Gravity - { - get { return gravity; } - } - - public static float HeightLevel0 - { - get { return heightLevel0; } - } - - public static float HeightLevel1 - { - get { return heightLevel1; } - } - - public static float LowGravityFactor - { - get { return lowGravityFactor; } - } - - public static int MaxXY - { - get { return maxXY; } - } - - public static int MaxZ - { - get { return maxZ; } - } - - private List _forgottenRigidBodies = new List(); - internal string is_ex_message = "Can't remove rigidBody!: "; - - #endregion - - public BulletXScene() - { - cDispatcher = new CollisionDispatcherLocal(this); - Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ); - Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ); - opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); - sicSolver = new SequentialImpulseConstraintSolver(); - - lock (BulletXLock) - { - ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver); - ddWorld.Gravity = new Vector3(0, 0, -gravity); - } - //this._heightmap = new float[65536]; - } - - public override void Initialise(IMesher meshmerizer) - { - mesher = meshmerizer; - } - - - public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID) - { - PhysicsVector pos = new PhysicsVector(); - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z + 20; - BulletXCharacter newAv = null; - lock (BulletXLock) - { - newAv = new BulletXCharacter(avName, this, pos); - _characters.Add(newAv.RigidBody, newAv); - } - return newAv; - } - - public override void RemoveAvatar(PhysicsActor actor) - { - if (actor is BulletXCharacter) - { - lock (BulletXLock) - { - try - { - ddWorld.RemoveRigidBody(((BulletXCharacter) actor).RigidBody); - } - catch (Exception ex) - { - BulletXMessage(is_ex_message + ex.Message, true); - ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation; - AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody); - } - _characters.Remove(((BulletXCharacter) actor).RigidBody); - } - GC.Collect(); - } - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, AxiomQuaternion rotation, uint localID) - { - return AddPrimShape(primName, pbs, position, size, rotation, false,localID); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, AxiomQuaternion rotation, bool isPhysical, uint LocalID) - { - PhysicsActor result; - - switch (pbs.ProfileShape) - { - case ProfileShape.Square: - /// support simple box & hollow box now; later, more shapes - if (pbs.ProfileHollow == 0) - { - result = AddPrim(primName, position, size, rotation, null, null, isPhysical, LocalID); - } - else - { - IMesh mesh = mesher.CreateMesh(primName, pbs, size); - result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, LocalID); - } - break; - - default: - result = AddPrim(primName, position, size, rotation, null, null, isPhysical, LocalID); - break; - } - - return result; - } - - public PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation, - IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical, uint localID) - { - BulletXPrim newPrim = null; - lock (BulletXLock) - { - newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical); - _prims.Add(newPrim.RigidBody, newPrim); - } - return newPrim; - } - - public override void RemovePrim(PhysicsActor prim) - { - if (prim is BulletXPrim) - { - lock (BulletXLock) - { - try - { - ddWorld.RemoveRigidBody(((BulletXPrim) prim).RigidBody); - } - catch (Exception ex) - { - BulletXMessage(is_ex_message + ex.Message, true); - ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation; - AddForgottenRigidBody(((BulletXPrim) prim).RigidBody); - } - _prims.Remove(((BulletXPrim) prim).RigidBody); - } - GC.Collect(); - } - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - float fps = 0; - lock (BulletXLock) - { - //Try to remove garbage - RemoveForgottenRigidBodies(); - //End of remove - MoveAllObjects(timeStep); - - - fps = (timeStep*simulationSubSteps); - - ddWorld.StepSimulation(timeStep, simulationSubSteps, timeStep); - //Extra Heightmap Validation: BulletX's HeightFieldTerrain somestimes doesn't work so fine. - ValidateHeightForAll(); - //End heightmap validation. - UpdateKineticsForAll(); - } - return fps; - } - - private void MoveAllObjects(float timeStep) - { - foreach (BulletXCharacter actor in _characters.Values) - { - actor.Move(timeStep); - } - foreach (BulletXPrim prim in _prims.Values) - { - } - } - - private void ValidateHeightForAll() - { - float _height; - foreach (BulletXCharacter actor in _characters.Values) - { - //_height = HeightValue(actor.RigidBodyPosition); - _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition); - actor.ValidateHeight(_height); - //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height); - } - foreach (BulletXPrim prim in _prims.Values) - { - //_height = HeightValue(prim.RigidBodyPosition); - _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition); - prim.ValidateHeight(_height); - //if (_simFlatPlanet.heightIsNotValid(prim.RigidBodyPosition, out _height)) prim.ValidateHeight(_height); - } - //foreach (BulletXCharacter actor in _characters) - //{ - // actor.ValidateHeight(0); - //} - //foreach (BulletXPrim prim in _prims) - //{ - // prim.ValidateHeight(0); - //} - } - - private void UpdateKineticsForAll() - { - //UpdatePosition > UpdateKinetics. - //Not only position will be updated, also velocity cause acceleration. - foreach (BulletXCharacter actor in _characters.Values) - { - actor.UpdateKinetics(); - } - foreach (BulletXPrim prim in _prims.Values) - { - prim.UpdateKinetics(); - } - //if(this._simFlatPlanet!=null) this._simFlatPlanet.Restore(); - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - get { return (false); // for now we won't be multithreaded - } - } - - public override void SetTerrain(float[] heightMap) - { - ////As the same as ODE, heightmap (x,y) must be swapped for BulletX - //for (int i = 0; i < 65536; i++) - //{ - // // this._heightmap[i] = (double)heightMap[i]; - // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) - // int x = i & 0xff; - // int y = i >> 8; - // this._heightmap[i] = heightMap[x * 256 + y]; - //} - - //float[] swappedHeightMap = new float[65536]; - ////As the same as ODE, heightmap (x,y) must be swapped for BulletX - //for (int i = 0; i < 65536; i++) - //{ - // // this._heightmap[i] = (double)heightMap[i]; - // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) - // int x = i & 0xff; - // int y = i >> 8; - // swappedHeightMap[i] = heightMap[x * 256 + y]; - //} - DeleteTerrain(); - //There is a BulletXLock inside the constructor of BulletXPlanet - //this._simFlatPlanet = new BulletXPlanet(this, swappedHeightMap); - _simFlatPlanet = new BulletXPlanet(this, heightMap); - //this._heightmap = heightMap; - } - - public override void DeleteTerrain() - { - if (_simFlatPlanet != null) - { - lock (BulletXLock) - { - try - { - ddWorld.RemoveRigidBody(_simFlatPlanet.RigidBody); - } - catch (Exception ex) - { - BulletXMessage(is_ex_message + ex.Message, true); - _simFlatPlanet.RigidBody.ActivationState = ActivationState.DisableSimulation; - AddForgottenRigidBody(_simFlatPlanet.RigidBody); - } - } - _simFlatPlanet = null; - GC.Collect(); - BulletXMessage("Terrain erased!", false); - } - //this._heightmap = null; - } - - internal void AddForgottenRigidBody(RigidBody forgottenRigidBody) - { - _forgottenRigidBodies.Add(forgottenRigidBody); - } - - private void RemoveForgottenRigidBodies() - { - RigidBody forgottenRigidBody; - int nRigidBodies = _forgottenRigidBodies.Count; - for (int i = nRigidBodies - 1; i >= 0; i--) - { - forgottenRigidBody = _forgottenRigidBodies[i]; - try - { - ddWorld.RemoveRigidBody(forgottenRigidBody); - _forgottenRigidBodies.Remove(forgottenRigidBody); - BulletXMessage("Forgotten Rigid Body Removed", false); - } - catch (Exception ex) - { - BulletXMessage("Can't remove forgottenRigidBody!: " + ex.Message, false); - } - } - GC.Collect(); - } - - internal void BulletXMessage(string message, bool isWarning) - { - PhysicsPluginManager.PhysicsPluginMessage("[Modified BulletX]:\t" + message, isWarning); - } - - //temp - //private float HeightValue(MonoXnaCompactMaths.Vector3 position) - //{ - // int li_x, li_y; - // float height; - // li_x = (int)Math.Round(position.X); if (li_x < 0) li_x = 0; - // li_y = (int)Math.Round(position.Y); if (li_y < 0) li_y = 0; - - // height = this._heightmap[li_y * 256 + li_x]; - // if (height < 0) height = 0; - // else if (height > maxZ) height = maxZ; - - // return height; - //} - } - - /// - /// Generic Physics Actor for BulletX inherit from PhysicActor - /// - public class BulletXActor : PhysicsActor - { - protected bool flying = false; - protected bool _physical = false; - protected PhysicsVector _position; - protected PhysicsVector _velocity; - protected PhysicsVector _size; - protected PhysicsVector _acceleration; - protected AxiomQuaternion _orientation; - protected PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; - protected RigidBody rigidBody; - protected int m_PhysicsActorType; - private Boolean iscolliding = false; - internal string _name; - - public BulletXActor(String name) - { - _name = name; - } - - public override PhysicsVector Position - { - get { return _position; } - set - { - lock (BulletXScene.BulletXLock) - { - _position = value; - Translate(); - } - } - } - - public override PhysicsVector RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override PhysicsVector Velocity - { - get { return _velocity; } - set - { - lock (BulletXScene.BulletXLock) - { - //Static objects don' have linear velocity - if (_physical) - { - _velocity = value; - Speed(); - } - else - { - _velocity = new PhysicsVector(); - } - } - } - } - - public override PhysicsVector Size - { - get { return _size; } - set - { - lock (BulletXScene.BulletXLock) - { - _size = value; - } - } - } - - public override PhysicsVector Force - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - public override AxiomQuaternion Orientation - { - get { return _orientation; } - set - { - lock (BulletXScene.BulletXLock) - { - _orientation = value; - ReOrient(); - } - } - } - - public override float Mass - { - get { return ActorMass; } - } - - public virtual float ActorMass - { - get { return 0; } - } - - public override int PhysicsActorType - { - get { return (int) m_PhysicsActorType; } - set { m_PhysicsActorType = value; } - } - - public RigidBody RigidBody - { - get { return rigidBody; } - } - - public Vector3 RigidBodyPosition - { - get { return rigidBody.CenterOfMassPosition; } - } - - public override bool IsPhysical - { - get { return _physical; } - set { _physical = value; } - } - - public override bool Flying - { - get { return flying; } - set { flying = value; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public virtual void SetAcceleration(PhysicsVector accel) - { - lock (BulletXScene.BulletXLock) - { - _acceleration = accel; - } - } - - public override bool Kinematic - { - get { return false; } - set { } - } - - public override void AddForce(PhysicsVector force) - { - } - - public override void SetMomentum(PhysicsVector momentum) - { - } - - internal virtual void ValidateHeight(float heighmapPositionValue) - { - } - - internal virtual void UpdateKinetics() - { - } - - #region Methods for updating values of RigidBody - - protected internal void Translate() - { - Translate(_position); - } - - protected internal void Translate(PhysicsVector _newPos) - { - Vector3 _translation; - _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition; - rigidBody.Translate(_translation); - } - - protected internal void Speed() - { - Speed(_velocity); - } - - protected internal void Speed(PhysicsVector _newSpeed) - { - Vector3 _speed; - _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed); - rigidBody.LinearVelocity = _speed; - } - - protected internal void ReOrient() - { - ReOrient(_orientation); - } - - protected internal void ReOrient(AxiomQuaternion _newOrient) - { - Quaternion _newOrientation; - _newOrientation = BulletXMaths.AxiomQuaternionToXnaQuaternion(_newOrient); - Matrix _comTransform = rigidBody.CenterOfMassTransform; - BulletXMaths.SetRotation(ref _comTransform, _newOrientation); - rigidBody.CenterOfMassTransform = _comTransform; - } - - protected internal void ReSize() - { - ReSize(_size); - } - - protected internal virtual void ReSize(PhysicsVector _newSize) - { - } - - public virtual void ScheduleTerseUpdate() - { - base.RequestPhysicsterseUpdate(); - } - - #endregion - } - - /// - /// PhysicsActor Character Class for BulletX - /// - public class BulletXCharacter : BulletXActor - { - public BulletXCharacter(BulletXScene parent_scene, PhysicsVector pos) - : this("", parent_scene, pos) - { - } - - public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos) - : this(avName, parent_scene, pos, new PhysicsVector(), new PhysicsVector(), new PhysicsVector(), - AxiomQuaternion.Identity) - { - } - - public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, - PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation) - : base(avName) - { - //This fields will be removed. They're temporal - float _sizeX = 0.5f; - float _sizeY = 0.5f; - float _sizeZ = 1.6f; - //. - _position = pos; - _velocity = velocity; - _size = size; - //--- - _size.X = _sizeX; - _size.Y = _sizeY; - _size.Z = _sizeZ; - //. - _acceleration = acceleration; - _orientation = orientation; - _physical = true; - - float _mass = 50.0f; //This depends of avatar's dimensions - //For RigidBody Constructor. The next values might change - float _linearDamping = 0.0f; - float _angularDamping = 0.0f; - float _friction = 0.5f; - float _restitution = 0.0f; - Matrix _startTransform = Matrix.Identity; - Matrix _centerOfMassOffset = Matrix.Identity; - lock (BulletXScene.BulletXLock) - { - _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); - //CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(1.0f, 1.0f, 1.60f)); - //For now, like ODE, collisionShape = sphere of radious = 1.0 - CollisionShape _collisionShape = new SphereShape(1.0f); - DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); - Vector3 _localInertia = new Vector3(); - _collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 - rigidBody = - new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, - _friction, _restitution); - //rigidBody.ActivationState = ActivationState.DisableDeactivation; - //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition - Vector3 _vDebugTranslation; - _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; - rigidBody.Translate(_vDebugTranslation); - parent_scene.ddWorld.AddRigidBody(rigidBody); - } - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override PhysicsVector Position - { - get { return base.Position; } - set { base.Position = value; } - } - - public override PhysicsVector Velocity - { - get { return base.Velocity; } - set { base.Velocity = value; } - } - - public override PhysicsVector Size - { - get { return base.Size; } - set { base.Size = value; } - } - - public override PhysicsVector Acceleration - { - get { return base.Acceleration; } - } - - public override AxiomQuaternion Orientation - { - get { return base.Orientation; } - set { base.Orientation = value; } - } - - public override bool Flying - { - get { return base.Flying; } - set { base.Flying = value; } - } - - public override bool IsColliding - { - get { return base.IsColliding; } - set { base.IsColliding = value; } - } - - public override bool Kinematic - { - get { return base.Kinematic; } - set { base.Kinematic = value; } - } - - public override void SetAcceleration(PhysicsVector accel) - { - base.SetAcceleration(accel); - } - - public override void AddForce(PhysicsVector force) - { - base.AddForce(force); - } - - public override void SetMomentum(PhysicsVector momentum) - { - base.SetMomentum(momentum); - } - - internal void Move(float timeStep) - { - Vector3 vec = new Vector3(); - //At this point it's supossed that: - //_velocity == rigidBody.LinearVelocity - vec.X = _velocity.X; - vec.Y = _velocity.Y; - vec.Z = _velocity.Z; - if ((vec.X != 0.0f) || (vec.Y != 0.0f) || (vec.Z != 0.0f)) rigidBody.Activate(); - if (flying) - { - //Antigravity with movement - if (_position.Z <= BulletXScene.HeightLevel0) - { - vec.Z += BulletXScene.Gravity*timeStep; - } - //Lowgravity with movement - else if ((_position.Z > BulletXScene.HeightLevel0) - && (_position.Z <= BulletXScene.HeightLevel1)) - { - vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); - } - //Lowgravity with... - else if (_position.Z > BulletXScene.HeightLevel1) - { - if (vec.Z > 0) //no movement - vec.Z = BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); - else - vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); - } - } - rigidBody.LinearVelocity = vec; - } - - //This validation is very basic - internal override void ValidateHeight(float heighmapPositionValue) - { - if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f) - { - Matrix m = rigidBody.WorldTransform; - Vector3 v3 = m.Translation; - v3.Z = heighmapPositionValue + _size.Z/2.0f; - m.Translation = v3; - rigidBody.WorldTransform = m; - //When an Avie touch the ground it's vertical velocity it's reduced to ZERO - Speed(new PhysicsVector(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f)); - } - } - - internal override void UpdateKinetics() - { - _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); - _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); - //Orientation it seems that it will be the default. - ReOrient(); - } - } - - /// - /// PhysicsActor Prim Class for BulletX - /// - public class BulletXPrim : BulletXActor - { - //Density it will depends of material. - //For now all prims have the same density, all prims are made of water. Be water my friend! :D - private const float _density = 1000.0f; - private BulletXScene _parent_scene; - private PhysicsVector m_prev_position = new PhysicsVector(0, 0, 0); - private bool m_lastUpdateSent = false; - - public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, - AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) - : this( - primName, parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, mesh, pbs, - isPhysical) - { - } - - public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, - PhysicsVector size, - PhysicsVector acceleration, AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, - bool isPhysical) - : base(primName) - { - if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0"); - if (rotation.Norm == 0f) rotation = AxiomQuaternion.Identity; - - _position = pos; - _physical = isPhysical; - _velocity = _physical ? velocity : new PhysicsVector(); - _size = size; - _acceleration = acceleration; - _orientation = rotation; - - _parent_scene = parent_scene; - - CreateRigidBody(parent_scene, mesh, pos, size); - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Prim; } - set { return; } - } - - public override PhysicsVector Position - { - get { return base.Position; } - set { base.Position = value; } - } - - public override PhysicsVector Velocity - { - get { return base.Velocity; } - set { base.Velocity = value; } - } - - public override PhysicsVector Size - { - get { return _size; } - set - { - lock (BulletXScene.BulletXLock) - { - _size = value; - ReSize(); - } - } - } - - public override PhysicsVector Acceleration - { - get { return base.Acceleration; } - } - - public override AxiomQuaternion Orientation - { - get { return base.Orientation; } - set { base.Orientation = value; } - } - - public override float ActorMass - { - get - { - //For now all prims are boxes - return (_physical ? 1 : 0)*_density*_size.X*_size.Y*_size.Z; - } - } - - public override bool IsPhysical - { - get { return base.IsPhysical; } - set - { - base.IsPhysical = value; - if (value) - { - //--- - PhysicsPluginManager.PhysicsPluginMessage("Physical - Recreate", true); - //--- - ReCreateRigidBody(_size); - } - else - { - //--- - PhysicsPluginManager.PhysicsPluginMessage("Physical - SetMassProps", true); - //--- - rigidBody.SetMassProps(Mass, new Vector3()); - } - } - } - - public override bool Flying - { - get { return base.Flying; } - set { base.Flying = value; } - } - - public override bool IsColliding - { - get { return base.IsColliding; } - set { base.IsColliding = value; } - } - - public override bool Kinematic - { - get { return base.Kinematic; } - set { base.Kinematic = value; } - } - - public override void SetAcceleration(PhysicsVector accel) - { - lock (BulletXScene.BulletXLock) - { - _acceleration = accel; - } - } - - public override void AddForce(PhysicsVector force) - { - base.AddForce(force); - } - - public override void SetMomentum(PhysicsVector momentum) - { - base.SetMomentum(momentum); - } - - internal override void ValidateHeight(float heighmapPositionValue) - { - if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f) - { - Matrix m = rigidBody.WorldTransform; - Vector3 v3 = m.Translation; - v3.Z = heighmapPositionValue + _size.Z/2.0f; - m.Translation = v3; - rigidBody.WorldTransform = m; - //When a Prim touch the ground it's vertical velocity it's reduced to ZERO - //Static objects don't have linear velocity - if (_physical) - Speed(new PhysicsVector(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f)); - } - } - - internal override void UpdateKinetics() - { - if (_physical) //Updates properties. Prim updates its properties physically - { - _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); - - _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); - _orientation = BulletXMaths.XnaQuaternionToAxiomQuaternion(rigidBody.Orientation); - - if ((Math.Abs(m_prev_position.X - _position.X) < 0.03) - && (Math.Abs(m_prev_position.Y - _position.Y) < 0.03) - && (Math.Abs(m_prev_position.Z - _position.Z) < 0.03)) - { - if (!m_lastUpdateSent) - { - _velocity = new PhysicsVector(0, 0, 0); - base.ScheduleTerseUpdate(); - m_lastUpdateSent = true; - } - } - else - { - m_lastUpdateSent = false; - base.ScheduleTerseUpdate(); - } - m_prev_position = _position; - } - else //Doesn't updates properties. That's a cancel - { - Translate(); - //Speed(); //<- Static objects don't have linear velocity - ReOrient(); - } - } - - #region Methods for updating values of RigidBody - - protected internal void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, PhysicsVector pos, - PhysicsVector size) - { - //For RigidBody Constructor. The next values might change - float _linearDamping = 0.0f; - float _angularDamping = 0.0f; - float _friction = 1.0f; - float _restitution = 0.0f; - Matrix _startTransform = Matrix.Identity; - Matrix _centerOfMassOffset = Matrix.Identity; - lock (BulletXScene.BulletXLock) - { - _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); - //For now all prims are boxes - CollisionShape _collisionShape; - if (mesh == null) - { - _collisionShape = new BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size)/2.0f); - } - else - { - int iVertexCount = mesh.getVertexList().Count; - int[] indices = mesh.getIndexListAsInt(); - Vector3[] v3Vertices = new Vector3[iVertexCount]; - for (int i = 0; i < iVertexCount; i++) - { - PhysicsVector v = mesh.getVertexList()[i]; - if (v != null) // Note, null has special meaning. See meshing code for details - v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v); - else - v3Vertices[i] = Vector3.Zero; - } - TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices); - - _collisionShape = new TriangleMeshShape(triMesh); - } - DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); - Vector3 _localInertia = new Vector3(); - if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0 - rigidBody = - new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, - _friction, _restitution); - //rigidBody.ActivationState = ActivationState.DisableDeactivation; - //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition - Vector3 _vDebugTranslation; - _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; - rigidBody.Translate(_vDebugTranslation); - //--- - parent_scene.ddWorld.AddRigidBody(rigidBody); - } - } - - protected internal void ReCreateRigidBody(PhysicsVector size) - { - //There is a bug when trying to remove a rigidBody that is colliding with something.. - try - { - _parent_scene.ddWorld.RemoveRigidBody(rigidBody); - } - catch (Exception ex) - { - _parent_scene.BulletXMessage(_parent_scene.is_ex_message + ex.Message, true); - rigidBody.ActivationState = ActivationState.DisableSimulation; - _parent_scene.AddForgottenRigidBody(rigidBody); - } - CreateRigidBody(_parent_scene, null, _position, size); - // Note, null for the meshing definitely is wrong. It's here for the moment to apease the compiler - if (_physical) Speed(); //Static objects don't have linear velocity - ReOrient(); - GC.Collect(); - } - - protected internal override void ReSize(PhysicsVector _newSize) - { - //I wonder to know how to resize with a simple instruction in BulletX. It seems that for now there isn't - //so i have to do it manually. That's recreating rigidbody - ReCreateRigidBody(_newSize); - } - - #endregion - } - - /// - /// This Class manage a HeighField as a RigidBody. This is for to be added in the BulletXScene - /// - internal class BulletXPlanet - { - private PhysicsVector _staticPosition; - private PhysicsVector _staticVelocity; - private AxiomQuaternion _staticOrientation; - private float _mass; - private BulletXScene _parentscene; - internal float[] _heightField; - private RigidBody _flatPlanet; - - internal RigidBody RigidBody - { - get { return _flatPlanet; } - } - - internal BulletXPlanet(BulletXScene parent_scene, float[] heightField) - { - _staticPosition = new PhysicsVector(BulletXScene.MaxXY/2, BulletXScene.MaxXY/2, 0); - _staticVelocity = new PhysicsVector(); - _staticOrientation = AxiomQuaternion.Identity; - _mass = 0; //No active - _parentscene = parent_scene; - _heightField = heightField; - - float _linearDamping = 0.0f; - float _angularDamping = 0.0f; - float _friction = 0.5f; - float _restitution = 0.0f; - Matrix _startTransform = Matrix.Identity; - Matrix _centerOfMassOffset = Matrix.Identity; - - lock (BulletXScene.BulletXLock) - { - try - { - _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(_staticPosition); - CollisionShape _collisionShape = - new HeightfieldTerrainShape(BulletXScene.MaxXY, BulletXScene.MaxXY, _heightField, - (float) BulletXScene.MaxZ, 2, true, false); - DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); - Vector3 _localInertia = new Vector3(); - //_collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 - _flatPlanet = - new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, - _angularDamping, _friction, _restitution); - //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition - Vector3 _vDebugTranslation; - _vDebugTranslation = _startTransform.Translation - _flatPlanet.CenterOfMassPosition; - _flatPlanet.Translate(_vDebugTranslation); - parent_scene.ddWorld.AddRigidBody(_flatPlanet); - } - catch (Exception ex) - { - _parentscene.BulletXMessage(ex.Message, true); - } - } - _parentscene.BulletXMessage("BulletXPlanet created.", false); - } - - internal float HeightValue(Vector3 position) - { - int li_x, li_y; - float height; - li_x = (int) Math.Round(position.X); - if (li_x < 0) li_x = 0; - if (li_x >= BulletXScene.MaxXY) li_x = BulletXScene.MaxXY - 1; - li_y = (int) Math.Round(position.Y); - if (li_y < 0) li_y = 0; - if (li_y >= BulletXScene.MaxXY) li_y = BulletXScene.MaxXY - 1; - - height = ((HeightfieldTerrainShape) _flatPlanet.CollisionShape).getHeightFieldValue(li_x, li_y); - if (height < 0) height = 0; - else if (height > BulletXScene.MaxZ) height = BulletXScene.MaxZ; - - return height; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#region Copyright + +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +#endregion + +#region References + +using System; +using System.Collections.Generic; +using MonoXnaCompactMaths; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; +using XnaDevRu.BulletX; +using XnaDevRu.BulletX.Dynamics; +using AxiomQuaternion = Axiom.Math.Quaternion; +using BoxShape=XnaDevRu.BulletX.BoxShape; + +#endregion + +namespace OpenSim.Region.Physics.BulletXPlugin +{ + /// + /// BulletXConversions are called now BulletXMaths + /// This Class converts objects and types for BulletX and give some operations + /// + public class BulletXMaths + { + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + //Vector3 + public static Vector3 PhysicsVectorToXnaVector3(PhysicsVector physicsVector) + { + return new Vector3(physicsVector.X, physicsVector.Y, physicsVector.Z); + } + + public static PhysicsVector XnaVector3ToPhysicsVector(Vector3 xnaVector3) + { + return new PhysicsVector(xnaVector3.X, xnaVector3.Y, xnaVector3.Z); + } + + //Quaternion + public static Quaternion AxiomQuaternionToXnaQuaternion(AxiomQuaternion axiomQuaternion) + { + return new Quaternion(axiomQuaternion.x, axiomQuaternion.y, axiomQuaternion.z, axiomQuaternion.w); + } + + public static AxiomQuaternion XnaQuaternionToAxiomQuaternion(Quaternion xnaQuaternion) + { + return new AxiomQuaternion(xnaQuaternion.W, xnaQuaternion.X, xnaQuaternion.Y, xnaQuaternion.Z); + } + + //Next methods are extracted from XnaDevRu.BulletX(See 3rd party license): + //- SetRotation (class MatrixOperations) + //- GetRotation (class MatrixOperations) + //- GetElement (class MathHelper) + //- SetElement (class MathHelper) + internal static void SetRotation(ref Matrix m, Quaternion q) + { + float d = q.LengthSquared(); + float s = 2f/d; + float xs = q.X*s, ys = q.Y*s, zs = q.Z*s; + float wx = q.W*xs, wy = q.W*ys, wz = q.W*zs; + float xx = q.X*xs, xy = q.X*ys, xz = q.X*zs; + float yy = q.Y*ys, yz = q.Y*zs, zz = q.Z*zs; + m = new Matrix(1 - (yy + zz), xy - wz, xz + wy, 0, + xy + wz, 1 - (xx + zz), yz - wx, 0, + xz - wy, yz + wx, 1 - (xx + yy), 0, + m.M41, m.M42, m.M43, 1); + } + + internal static Quaternion GetRotation(Matrix m) + { + Quaternion q = new Quaternion(); + + float trace = m.M11 + m.M22 + m.M33; + + if (trace > 0) + { + float s = (float) Math.Sqrt(trace + 1); + q.W = s*0.5f; + s = 0.5f/s; + + q.X = (m.M32 - m.M23)*s; + q.Y = (m.M13 - m.M31)*s; + q.Z = (m.M21 - m.M12)*s; + } + else + { + int i = m.M11 < m.M22 + ? + (m.M22 < m.M33 ? 2 : 1) + : + (m.M11 < m.M33 ? 2 : 0); + int j = (i + 1)%3; + int k = (i + 2)%3; + + float s = (float) Math.Sqrt(GetElement(m, i, i) - GetElement(m, j, j) - GetElement(m, k, k) + 1); + SetElement(ref q, i, s*0.5f); + s = 0.5f/s; + + q.W = (GetElement(m, k, j) - GetElement(m, j, k))*s; + SetElement(ref q, j, (GetElement(m, j, i) + GetElement(m, i, j))*s); + SetElement(ref q, k, (GetElement(m, k, i) + GetElement(m, i, k))*s); + } + + return q; + } + + internal static float SetElement(ref Quaternion q, int index, float value) + { + switch (index) + { + case 0: + q.X = value; + break; + case 1: + q.Y = value; + break; + case 2: + q.Z = value; + break; + case 3: + q.W = value; + break; + } + + return 0; + } + + internal static float GetElement(Matrix mat, int row, int col) + { + switch (row) + { + case 0: + switch (col) + { + case 0: + return mat.M11; + case 1: + return mat.M12; + case 2: + return mat.M13; + } + break; + case 1: + switch (col) + { + case 0: + return mat.M21; + case 1: + return mat.M22; + case 2: + return mat.M23; + } + break; + case 2: + switch (col) + { + case 0: + return mat.M31; + case 1: + return mat.M32; + case 2: + return mat.M33; + } + break; + } + + return 0; + } + } + + /// + /// PhysicsPlugin Class for BulletX + /// + public class BulletXPlugin : IPhysicsPlugin + { + private BulletXScene _mScene; + + public BulletXPlugin() + { + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + if (_mScene == null) + { + _mScene = new BulletXScene(); + } + return (_mScene); + } + + public string GetName() + { + return ("modified_BulletX"); //Changed!! "BulletXEngine" To "modified_BulletX" + } + + public void Dispose() + { + } + } + + + // Class to detect and debug collisions + // Mainly used for debugging purposes + internal class CollisionDispatcherLocal : CollisionDispatcher + { + private BulletXScene relatedScene; + + public CollisionDispatcherLocal(BulletXScene s) + : base() + { + relatedScene = s; + } + + public override bool NeedsCollision(CollisionObject bodyA, CollisionObject bodyB) + { + RigidBody rb; + BulletXCharacter bxcA = null; + BulletXPrim bxpA = null; + Type t = bodyA.GetType(); + if (t == typeof (RigidBody)) + { + rb = (RigidBody) bodyA; + relatedScene._characters.TryGetValue(rb, out bxcA); + relatedScene._prims.TryGetValue(rb, out bxpA); + } + String nameA; + if (bxcA != null) + nameA = bxcA._name; + else if (bxpA != null) + nameA = bxpA._name; + else + nameA = "null"; + + BulletXCharacter bxcB = null; + BulletXPrim bxpB = null; + t = bodyB.GetType(); + if (t == typeof (RigidBody)) + { + rb = (RigidBody) bodyB; + relatedScene._characters.TryGetValue(rb, out bxcB); + relatedScene._prims.TryGetValue(rb, out bxpB); + } + String nameB; + if (bxcB != null) + nameB = bxcB._name; + else if (bxpB != null) + nameB = bxpB._name; + else + nameB = "null"; + + bool needsCollision = base.NeedsCollision(bodyA, bodyB); + + //m_log.DebugFormat("[BulletX]: A collision was detected between {0} and {1} --> {2}", nameA, nameB, + //needsCollision); + + return needsCollision; + } + } + + /// + /// PhysicsScene Class for BulletX + /// + public class BulletXScene : PhysicsScene + { + #region BulletXScene Fields + + public DiscreteDynamicsWorld ddWorld; + private CollisionDispatcher cDispatcher; + private OverlappingPairCache opCache; + private SequentialImpulseConstraintSolver sicSolver; + public static Object BulletXLock = new Object(); + + private const int minXY = 0; + private const int minZ = 0; + private const int maxXY = (int)Constants.RegionSize; + private const int maxZ = 4096; + private const int maxHandles = 32766; //Why? I don't know + private const float gravity = 9.8f; + private const float heightLevel0 = 77.0f; + private const float heightLevel1 = 200.0f; + private const float lowGravityFactor = 0.2f; + //OpenSim calls Simulate 10 times per seconds. So FPS = "Simulate Calls" * simulationSubSteps = 100 FPS + private const int simulationSubSteps = 10; + //private float[] _heightmap; + private BulletXPlanet _simFlatPlanet; + internal Dictionary _characters = new Dictionary(); + internal Dictionary _prims = new Dictionary(); + + public IMesher mesher; + + + public static float Gravity + { + get { return gravity; } + } + + public static float HeightLevel0 + { + get { return heightLevel0; } + } + + public static float HeightLevel1 + { + get { return heightLevel1; } + } + + public static float LowGravityFactor + { + get { return lowGravityFactor; } + } + + public static int MaxXY + { + get { return maxXY; } + } + + public static int MaxZ + { + get { return maxZ; } + } + + private List _forgottenRigidBodies = new List(); + internal string is_ex_message = "Can't remove rigidBody!: "; + + #endregion + + public BulletXScene() + { + cDispatcher = new CollisionDispatcherLocal(this); + Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ); + Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ); + opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles); + sicSolver = new SequentialImpulseConstraintSolver(); + + lock (BulletXLock) + { + ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver); + ddWorld.Gravity = new Vector3(0, 0, -gravity); + } + //this._heightmap = new float[65536]; + } + + public override void Initialise(IMesher meshmerizer) + { + mesher = meshmerizer; + } + + public override void Dispose() + { + + } + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + PhysicsVector pos = new PhysicsVector(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z + 20; + BulletXCharacter newAv = null; + lock (BulletXLock) + { + newAv = new BulletXCharacter(avName, this, pos); + _characters.Add(newAv.RigidBody, newAv); + } + return newAv; + } + + public override void RemoveAvatar(PhysicsActor actor) + { + if (actor is BulletXCharacter) + { + lock (BulletXLock) + { + try + { + ddWorld.RemoveRigidBody(((BulletXCharacter) actor).RigidBody); + } + catch (Exception ex) + { + BulletXMessage(is_ex_message + ex.Message, true); + ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation; + AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody); + } + _characters.Remove(((BulletXCharacter) actor).RigidBody); + } + GC.Collect(); + } + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, AxiomQuaternion rotation, uint localID) + { + return AddPrimShape(primName, pbs, position, size, rotation, false,localID); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, AxiomQuaternion rotation, bool isPhysical, uint LocalID) + { + PhysicsActor result; + + switch (pbs.ProfileShape) + { + case ProfileShape.Square: + /// support simple box & hollow box now; later, more shapes + if (pbs.ProfileHollow == 0) + { + result = AddPrim(primName, position, size, rotation, null, null, isPhysical, LocalID); + } + else + { + IMesh mesh = mesher.CreateMesh(primName, pbs, size); + result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, LocalID); + } + break; + + default: + result = AddPrim(primName, position, size, rotation, null, null, isPhysical, LocalID); + break; + } + + return result; + } + + public PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation, + IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical, uint localID) + { + BulletXPrim newPrim = null; + lock (BulletXLock) + { + newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical); + _prims.Add(newPrim.RigidBody, newPrim); + } + return newPrim; + } + + public override void RemovePrim(PhysicsActor prim) + { + if (prim is BulletXPrim) + { + lock (BulletXLock) + { + try + { + ddWorld.RemoveRigidBody(((BulletXPrim) prim).RigidBody); + } + catch (Exception ex) + { + BulletXMessage(is_ex_message + ex.Message, true); + ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation; + AddForgottenRigidBody(((BulletXPrim) prim).RigidBody); + } + _prims.Remove(((BulletXPrim) prim).RigidBody); + } + GC.Collect(); + } + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + float fps = 0; + lock (BulletXLock) + { + //Try to remove garbage + RemoveForgottenRigidBodies(); + //End of remove + MoveAllObjects(timeStep); + + + fps = (timeStep*simulationSubSteps); + + ddWorld.StepSimulation(timeStep, simulationSubSteps, timeStep); + //Extra Heightmap Validation: BulletX's HeightFieldTerrain somestimes doesn't work so fine. + ValidateHeightForAll(); + //End heightmap validation. + UpdateKineticsForAll(); + } + return fps; + } + + private void MoveAllObjects(float timeStep) + { + foreach (BulletXCharacter actor in _characters.Values) + { + actor.Move(timeStep); + } + foreach (BulletXPrim prim in _prims.Values) + { + } + } + + private void ValidateHeightForAll() + { + float _height; + foreach (BulletXCharacter actor in _characters.Values) + { + //_height = HeightValue(actor.RigidBodyPosition); + _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition); + actor.ValidateHeight(_height); + //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height); + } + foreach (BulletXPrim prim in _prims.Values) + { + //_height = HeightValue(prim.RigidBodyPosition); + _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition); + prim.ValidateHeight(_height); + //if (_simFlatPlanet.heightIsNotValid(prim.RigidBodyPosition, out _height)) prim.ValidateHeight(_height); + } + //foreach (BulletXCharacter actor in _characters) + //{ + // actor.ValidateHeight(0); + //} + //foreach (BulletXPrim prim in _prims) + //{ + // prim.ValidateHeight(0); + //} + } + + private void UpdateKineticsForAll() + { + //UpdatePosition > UpdateKinetics. + //Not only position will be updated, also velocity cause acceleration. + foreach (BulletXCharacter actor in _characters.Values) + { + actor.UpdateKinetics(); + } + foreach (BulletXPrim prim in _prims.Values) + { + prim.UpdateKinetics(); + } + //if(this._simFlatPlanet!=null) this._simFlatPlanet.Restore(); + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + get { return (false); // for now we won't be multithreaded + } + } + + public override void SetTerrain(float[] heightMap) + { + ////As the same as ODE, heightmap (x,y) must be swapped for BulletX + //for (int i = 0; i < 65536; i++) + //{ + // // this._heightmap[i] = (double)heightMap[i]; + // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) + // int x = i & 0xff; + // int y = i >> 8; + // this._heightmap[i] = heightMap[x * 256 + y]; + //} + + //float[] swappedHeightMap = new float[65536]; + ////As the same as ODE, heightmap (x,y) must be swapped for BulletX + //for (int i = 0; i < 65536; i++) + //{ + // // this._heightmap[i] = (double)heightMap[i]; + // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) + // int x = i & 0xff; + // int y = i >> 8; + // swappedHeightMap[i] = heightMap[x * 256 + y]; + //} + DeleteTerrain(); + //There is a BulletXLock inside the constructor of BulletXPlanet + //this._simFlatPlanet = new BulletXPlanet(this, swappedHeightMap); + _simFlatPlanet = new BulletXPlanet(this, heightMap); + //this._heightmap = heightMap; + } + + public override void DeleteTerrain() + { + if (_simFlatPlanet != null) + { + lock (BulletXLock) + { + try + { + ddWorld.RemoveRigidBody(_simFlatPlanet.RigidBody); + } + catch (Exception ex) + { + BulletXMessage(is_ex_message + ex.Message, true); + _simFlatPlanet.RigidBody.ActivationState = ActivationState.DisableSimulation; + AddForgottenRigidBody(_simFlatPlanet.RigidBody); + } + } + _simFlatPlanet = null; + GC.Collect(); + BulletXMessage("Terrain erased!", false); + } + //this._heightmap = null; + } + + internal void AddForgottenRigidBody(RigidBody forgottenRigidBody) + { + _forgottenRigidBodies.Add(forgottenRigidBody); + } + + private void RemoveForgottenRigidBodies() + { + RigidBody forgottenRigidBody; + int nRigidBodies = _forgottenRigidBodies.Count; + for (int i = nRigidBodies - 1; i >= 0; i--) + { + forgottenRigidBody = _forgottenRigidBodies[i]; + try + { + ddWorld.RemoveRigidBody(forgottenRigidBody); + _forgottenRigidBodies.Remove(forgottenRigidBody); + BulletXMessage("Forgotten Rigid Body Removed", false); + } + catch (Exception ex) + { + BulletXMessage("Can't remove forgottenRigidBody!: " + ex.Message, false); + } + } + GC.Collect(); + } + + internal void BulletXMessage(string message, bool isWarning) + { + PhysicsPluginManager.PhysicsPluginMessage("[Modified BulletX]:\t" + message, isWarning); + } + + //temp + //private float HeightValue(MonoXnaCompactMaths.Vector3 position) + //{ + // int li_x, li_y; + // float height; + // li_x = (int)Math.Round(position.X); if (li_x < 0) li_x = 0; + // li_y = (int)Math.Round(position.Y); if (li_y < 0) li_y = 0; + + // height = this._heightmap[li_y * 256 + li_x]; + // if (height < 0) height = 0; + // else if (height > maxZ) height = maxZ; + + // return height; + //} + } + + /// + /// Generic Physics Actor for BulletX inherit from PhysicActor + /// + public class BulletXActor : PhysicsActor + { + protected bool flying = false; + protected bool _physical = false; + protected PhysicsVector _position; + protected PhysicsVector _velocity; + protected PhysicsVector _size; + protected PhysicsVector _acceleration; + protected AxiomQuaternion _orientation; + protected PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + protected RigidBody rigidBody; + protected int m_PhysicsActorType; + private Boolean iscolliding = false; + internal string _name; + + public BulletXActor(String name) + { + _name = name; + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get { return _position; } + set + { + lock (BulletXScene.BulletXLock) + { + _position = value; + Translate(); + } + } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set + { + lock (BulletXScene.BulletXLock) + { + //Static objects don' have linear velocity + if (_physical) + { + _velocity = value; + Speed(); + } + else + { + _velocity = new PhysicsVector(); + } + } + } + } + public override float CollisionScore + { + get { return 0f; } + } + public override PhysicsVector Size + { + get { return _size; } + set + { + lock (BulletXScene.BulletXLock) + { + _size = value; + } + } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public override AxiomQuaternion Orientation + { + get { return _orientation; } + set + { + lock (BulletXScene.BulletXLock) + { + _orientation = value; + ReOrient(); + } + } + } + + public override float Mass + { + get { return ActorMass; } + } + + public virtual float ActorMass + { + get { return 0; } + } + + public override int PhysicsActorType + { + get { return (int) m_PhysicsActorType; } + set { m_PhysicsActorType = value; } + } + + public RigidBody RigidBody + { + get { return rigidBody; } + } + + public Vector3 RigidBodyPosition + { + get { return rigidBody.CenterOfMassPosition; } + } + + public override bool IsPhysical + { + get { return _physical; } + set { _physical = value; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public virtual void SetAcceleration(PhysicsVector accel) + { + lock (BulletXScene.BulletXLock) + { + _acceleration = accel; + } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + internal virtual void ValidateHeight(float heighmapPositionValue) + { + } + + internal virtual void UpdateKinetics() + { + } + + #region Methods for updating values of RigidBody + + protected internal void Translate() + { + Translate(_position); + } + + protected internal void Translate(PhysicsVector _newPos) + { + Vector3 _translation; + _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition; + rigidBody.Translate(_translation); + } + + protected internal void Speed() + { + Speed(_velocity); + } + + protected internal void Speed(PhysicsVector _newSpeed) + { + Vector3 _speed; + _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed); + rigidBody.LinearVelocity = _speed; + } + + protected internal void ReOrient() + { + ReOrient(_orientation); + } + + protected internal void ReOrient(AxiomQuaternion _newOrient) + { + Quaternion _newOrientation; + _newOrientation = BulletXMaths.AxiomQuaternionToXnaQuaternion(_newOrient); + Matrix _comTransform = rigidBody.CenterOfMassTransform; + BulletXMaths.SetRotation(ref _comTransform, _newOrientation); + rigidBody.CenterOfMassTransform = _comTransform; + } + + protected internal void ReSize() + { + ReSize(_size); + } + + protected internal virtual void ReSize(PhysicsVector _newSize) + { + } + + public virtual void ScheduleTerseUpdate() + { + base.RequestPhysicsterseUpdate(); + } + + #endregion + + public override void CrossingFailure() + { + + } + } + + /// + /// PhysicsActor Character Class for BulletX + /// + public class BulletXCharacter : BulletXActor + { + public BulletXCharacter(BulletXScene parent_scene, PhysicsVector pos) + : this(String.Empty, parent_scene, pos) + { + } + + public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos) + : this(avName, parent_scene, pos, new PhysicsVector(), new PhysicsVector(), new PhysicsVector(), + AxiomQuaternion.Identity) + { + } + + public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, + PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation) + : base(avName) + { + //This fields will be removed. They're temporal + float _sizeX = 0.5f; + float _sizeY = 0.5f; + float _sizeZ = 1.6f; + //. + _position = pos; + _velocity = velocity; + _size = size; + //--- + _size.X = _sizeX; + _size.Y = _sizeY; + _size.Z = _sizeZ; + //. + _acceleration = acceleration; + _orientation = orientation; + _physical = true; + + float _mass = 50.0f; //This depends of avatar's dimensions + //For RigidBody Constructor. The next values might change + float _linearDamping = 0.0f; + float _angularDamping = 0.0f; + float _friction = 0.5f; + float _restitution = 0.0f; + Matrix _startTransform = Matrix.Identity; + Matrix _centerOfMassOffset = Matrix.Identity; + lock (BulletXScene.BulletXLock) + { + _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); + //CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(1.0f, 1.0f, 1.60f)); + //For now, like ODE, collisionShape = sphere of radious = 1.0 + CollisionShape _collisionShape = new SphereShape(1.0f); + DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); + Vector3 _localInertia = new Vector3(); + _collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 + rigidBody = + new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, + _friction, _restitution); + //rigidBody.ActivationState = ActivationState.DisableDeactivation; + //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition + Vector3 _vDebugTranslation; + _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; + rigidBody.Translate(_vDebugTranslation); + parent_scene.ddWorld.AddRigidBody(rigidBody); + } + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + public override PhysicsVector Position + { + get { return base.Position; } + set { base.Position = value; } + } + + public override PhysicsVector Velocity + { + get { return base.Velocity; } + set { base.Velocity = value; } + } + + public override PhysicsVector Size + { + get { return base.Size; } + set { base.Size = value; } + } + + public override PhysicsVector Acceleration + { + get { return base.Acceleration; } + } + + public override AxiomQuaternion Orientation + { + get { return base.Orientation; } + set { base.Orientation = value; } + } + + public override bool Flying + { + get { return base.Flying; } + set { base.Flying = value; } + } + + public override bool IsColliding + { + get { return base.IsColliding; } + set { base.IsColliding = value; } + } + + public override bool Kinematic + { + get { return base.Kinematic; } + set { base.Kinematic = value; } + } + + public override void SetAcceleration(PhysicsVector accel) + { + base.SetAcceleration(accel); + } + + public override void AddForce(PhysicsVector force) + { + base.AddForce(force); + } + + public override void SetMomentum(PhysicsVector momentum) + { + base.SetMomentum(momentum); + } + + internal void Move(float timeStep) + { + Vector3 vec = new Vector3(); + //At this point it's supossed that: + //_velocity == rigidBody.LinearVelocity + vec.X = _velocity.X; + vec.Y = _velocity.Y; + vec.Z = _velocity.Z; + if ((vec.X != 0.0f) || (vec.Y != 0.0f) || (vec.Z != 0.0f)) rigidBody.Activate(); + if (flying) + { + //Antigravity with movement + if (_position.Z <= BulletXScene.HeightLevel0) + { + vec.Z += BulletXScene.Gravity*timeStep; + } + //Lowgravity with movement + else if ((_position.Z > BulletXScene.HeightLevel0) + && (_position.Z <= BulletXScene.HeightLevel1)) + { + vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); + } + //Lowgravity with... + else if (_position.Z > BulletXScene.HeightLevel1) + { + if (vec.Z > 0) //no movement + vec.Z = BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); + else + vec.Z += BulletXScene.Gravity*timeStep*(1.0f - BulletXScene.LowGravityFactor); + } + } + rigidBody.LinearVelocity = vec; + } + + //This validation is very basic + internal override void ValidateHeight(float heighmapPositionValue) + { + if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f) + { + Matrix m = rigidBody.WorldTransform; + Vector3 v3 = m.Translation; + v3.Z = heighmapPositionValue + _size.Z/2.0f; + m.Translation = v3; + rigidBody.WorldTransform = m; + //When an Avie touch the ground it's vertical velocity it's reduced to ZERO + Speed(new PhysicsVector(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f)); + } + } + + internal override void UpdateKinetics() + { + _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); + _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); + //Orientation it seems that it will be the default. + ReOrient(); + } + } + + /// + /// PhysicsActor Prim Class for BulletX + /// + public class BulletXPrim : BulletXActor + { + //Density it will depends of material. + //For now all prims have the same density, all prims are made of water. Be water my friend! :D + private const float _density = 1000.0f; + private BulletXScene _parent_scene; + private PhysicsVector m_prev_position = new PhysicsVector(0, 0, 0); + private bool m_lastUpdateSent = false; + + public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, + AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical) + : this( + primName, parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, mesh, pbs, + isPhysical) + { + } + + public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, + PhysicsVector size, + PhysicsVector acceleration, AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, + bool isPhysical) + : base(primName) + { + if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0"); + if (rotation.Norm == 0f) rotation = AxiomQuaternion.Identity; + + _position = pos; + _physical = isPhysical; + _velocity = _physical ? velocity : new PhysicsVector(); + _size = size; + _acceleration = acceleration; + _orientation = rotation; + + _parent_scene = parent_scene; + + CreateRigidBody(parent_scene, mesh, pos, size); + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Prim; } + set { return; } + } + + public override PhysicsVector Position + { + get { return base.Position; } + set { base.Position = value; } + } + + public override PhysicsVector Velocity + { + get { return base.Velocity; } + set { base.Velocity = value; } + } + + public override PhysicsVector Size + { + get { return _size; } + set + { + lock (BulletXScene.BulletXLock) + { + _size = value; + ReSize(); + } + } + } + + public override PhysicsVector Acceleration + { + get { return base.Acceleration; } + } + + public override AxiomQuaternion Orientation + { + get { return base.Orientation; } + set { base.Orientation = value; } + } + + public override float ActorMass + { + get + { + //For now all prims are boxes + return (_physical ? 1 : 0)*_density*_size.X*_size.Y*_size.Z; + } + } + + public override bool IsPhysical + { + get { return base.IsPhysical; } + set + { + base.IsPhysical = value; + if (value) + { + //--- + PhysicsPluginManager.PhysicsPluginMessage("Physical - Recreate", true); + //--- + ReCreateRigidBody(_size); + } + else + { + //--- + PhysicsPluginManager.PhysicsPluginMessage("Physical - SetMassProps", true); + //--- + rigidBody.SetMassProps(Mass, new Vector3()); + } + } + } + + public override bool Flying + { + get { return base.Flying; } + set { base.Flying = value; } + } + + public override bool IsColliding + { + get { return base.IsColliding; } + set { base.IsColliding = value; } + } + + public override bool Kinematic + { + get { return base.Kinematic; } + set { base.Kinematic = value; } + } + + public override void SetAcceleration(PhysicsVector accel) + { + lock (BulletXScene.BulletXLock) + { + _acceleration = accel; + } + } + + public override void AddForce(PhysicsVector force) + { + base.AddForce(force); + } + + public override void SetMomentum(PhysicsVector momentum) + { + base.SetMomentum(momentum); + } + + internal override void ValidateHeight(float heighmapPositionValue) + { + if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z/2.0f) + { + Matrix m = rigidBody.WorldTransform; + Vector3 v3 = m.Translation; + v3.Z = heighmapPositionValue + _size.Z/2.0f; + m.Translation = v3; + rigidBody.WorldTransform = m; + //When a Prim touch the ground it's vertical velocity it's reduced to ZERO + //Static objects don't have linear velocity + if (_physical) + Speed(new PhysicsVector(rigidBody.LinearVelocity.X, rigidBody.LinearVelocity.Y, 0.0f)); + } + } + + internal override void UpdateKinetics() + { + if (_physical) //Updates properties. Prim updates its properties physically + { + _position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition); + + _velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity); + _orientation = BulletXMaths.XnaQuaternionToAxiomQuaternion(rigidBody.Orientation); + + if ((Math.Abs(m_prev_position.X - _position.X) < 0.03) + && (Math.Abs(m_prev_position.Y - _position.Y) < 0.03) + && (Math.Abs(m_prev_position.Z - _position.Z) < 0.03)) + { + if (!m_lastUpdateSent) + { + _velocity = new PhysicsVector(0, 0, 0); + base.ScheduleTerseUpdate(); + m_lastUpdateSent = true; + } + } + else + { + m_lastUpdateSent = false; + base.ScheduleTerseUpdate(); + } + m_prev_position = _position; + } + else //Doesn't updates properties. That's a cancel + { + Translate(); + //Speed(); //<- Static objects don't have linear velocity + ReOrient(); + } + } + + #region Methods for updating values of RigidBody + + protected internal void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, PhysicsVector pos, + PhysicsVector size) + { + //For RigidBody Constructor. The next values might change + float _linearDamping = 0.0f; + float _angularDamping = 0.0f; + float _friction = 1.0f; + float _restitution = 0.0f; + Matrix _startTransform = Matrix.Identity; + Matrix _centerOfMassOffset = Matrix.Identity; + lock (BulletXScene.BulletXLock) + { + _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos); + //For now all prims are boxes + CollisionShape _collisionShape; + if (mesh == null) + { + _collisionShape = new BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size)/2.0f); + } + else + { + int iVertexCount = mesh.getVertexList().Count; + int[] indices = mesh.getIndexListAsInt(); + Vector3[] v3Vertices = new Vector3[iVertexCount]; + for (int i = 0; i < iVertexCount; i++) + { + PhysicsVector v = mesh.getVertexList()[i]; + if (v != null) // Note, null has special meaning. See meshing code for details + v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v); + else + v3Vertices[i] = Vector3.Zero; + } + TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices); + + _collisionShape = new TriangleMeshShape(triMesh); + } + DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); + Vector3 _localInertia = new Vector3(); + if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0 + rigidBody = + new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, + _friction, _restitution); + //rigidBody.ActivationState = ActivationState.DisableDeactivation; + //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition + Vector3 _vDebugTranslation; + _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition; + rigidBody.Translate(_vDebugTranslation); + //--- + parent_scene.ddWorld.AddRigidBody(rigidBody); + } + } + + protected internal void ReCreateRigidBody(PhysicsVector size) + { + //There is a bug when trying to remove a rigidBody that is colliding with something.. + try + { + _parent_scene.ddWorld.RemoveRigidBody(rigidBody); + } + catch (Exception ex) + { + _parent_scene.BulletXMessage(_parent_scene.is_ex_message + ex.Message, true); + rigidBody.ActivationState = ActivationState.DisableSimulation; + _parent_scene.AddForgottenRigidBody(rigidBody); + } + CreateRigidBody(_parent_scene, null, _position, size); + // Note, null for the meshing definitely is wrong. It's here for the moment to apease the compiler + if (_physical) Speed(); //Static objects don't have linear velocity + ReOrient(); + GC.Collect(); + } + + protected internal override void ReSize(PhysicsVector _newSize) + { + //I wonder to know how to resize with a simple instruction in BulletX. It seems that for now there isn't + //so i have to do it manually. That's recreating rigidbody + ReCreateRigidBody(_newSize); + } + + #endregion + } + + /// + /// This Class manage a HeighField as a RigidBody. This is for to be added in the BulletXScene + /// + internal class BulletXPlanet + { + private PhysicsVector _staticPosition; + private PhysicsVector _staticVelocity; + private AxiomQuaternion _staticOrientation; + private float _mass; + private BulletXScene _parentscene; + internal float[] _heightField; + private RigidBody _flatPlanet; + + internal RigidBody RigidBody + { + get { return _flatPlanet; } + } + + internal BulletXPlanet(BulletXScene parent_scene, float[] heightField) + { + _staticPosition = new PhysicsVector(BulletXScene.MaxXY/2, BulletXScene.MaxXY/2, 0); + _staticVelocity = new PhysicsVector(); + _staticOrientation = AxiomQuaternion.Identity; + _mass = 0; //No active + _parentscene = parent_scene; + _heightField = heightField; + + float _linearDamping = 0.0f; + float _angularDamping = 0.0f; + float _friction = 0.5f; + float _restitution = 0.0f; + Matrix _startTransform = Matrix.Identity; + Matrix _centerOfMassOffset = Matrix.Identity; + + lock (BulletXScene.BulletXLock) + { + try + { + _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(_staticPosition); + CollisionShape _collisionShape = + new HeightfieldTerrainShape(BulletXScene.MaxXY, BulletXScene.MaxXY, _heightField, + (float) BulletXScene.MaxZ, 2, true, false); + DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset); + Vector3 _localInertia = new Vector3(); + //_collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0 + _flatPlanet = + new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, + _angularDamping, _friction, _restitution); + //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition + Vector3 _vDebugTranslation; + _vDebugTranslation = _startTransform.Translation - _flatPlanet.CenterOfMassPosition; + _flatPlanet.Translate(_vDebugTranslation); + parent_scene.ddWorld.AddRigidBody(_flatPlanet); + } + catch (Exception ex) + { + _parentscene.BulletXMessage(ex.Message, true); + } + } + _parentscene.BulletXMessage("BulletXPlanet created.", false); + } + + internal float HeightValue(Vector3 position) + { + int li_x, li_y; + float height; + li_x = (int) Math.Round(position.X); + if (li_x < 0) li_x = 0; + if (li_x >= BulletXScene.MaxXY) li_x = BulletXScene.MaxXY - 1; + li_y = (int) Math.Round(position.Y); + if (li_y < 0) li_y = 0; + if (li_y >= BulletXScene.MaxXY) li_y = BulletXScene.MaxXY - 1; + + height = ((HeightfieldTerrainShape) _flatPlanet.CollisionShape).getHeightFieldValue(li_x, li_y); + if (height < 0) height = 0; + else if (height > BulletXScene.MaxZ) height = BulletXScene.MaxZ; + + return height; + } + } +} diff --git a/OpenSim/Region/Physics/Manager/CollisionLocker.cs b/OpenSim/Region/Physics/Manager/CollisionLocker.cs new file mode 100644 index 0000000000..98e9736a93 --- /dev/null +++ b/OpenSim/Region/Physics/Manager/CollisionLocker.cs @@ -0,0 +1,74 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.Physics.Manager +{ + public class CollisionLocker + { + + + private List worldlock = new List(); + public CollisionLocker() + { + + } + public void dlock(IntPtr world) + { + lock (worldlock) + { + worldlock.Add(world); + } + + } + public void dunlock(IntPtr world) + { + lock (worldlock) + { + worldlock.Remove(world); + } + } + public bool lockquery() + { + return (worldlock.Count > 0); + } + public void drelease(IntPtr world) + { + lock (worldlock) + { + if (worldlock.Contains(world)) + worldlock.Remove(world); + } + } + + } + +} diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 9f058dd6c3..c3dd880b96 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -1,324 +1,368 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -using System; -using System.Collections.Generic; -using Axiom.Math; -using OpenSim.Framework; - -namespace OpenSim.Region.Physics.Manager -{ - public delegate void PositionUpdate(PhysicsVector position); - - public delegate void VelocityUpdate(PhysicsVector velocity); - - public delegate void OrientationUpdate(Quaternion orientation); - - public enum ActorTypes : int - { - Unknown = 0, - Agent = 1, - Prim = 2, - Ground = 3, - PrimVolume = 4 // rex - } - - public class CollisionEventUpdate : EventArgs - { - // Raising the event on the object, so don't need to provide location.. further up the tree knows that info. - public int m_colliderType; - public bool m_startOrEnd; - public uint m_LocalID; // rex - public List m_objCollisionList; - - public CollisionEventUpdate(uint localID, int colliderType, bool startOrEnd, List objCollisionList) - { - m_LocalID = localID; // rex - m_colliderType = colliderType; - m_startOrEnd = startOrEnd; - m_objCollisionList = objCollisionList; - } - - public CollisionEventUpdate(bool startOrEnd) - { - m_colliderType = (int) ActorTypes.Unknown; - m_startOrEnd = startOrEnd; - m_objCollisionList = null; - } - - public CollisionEventUpdate() - { - m_colliderType = (int) ActorTypes.Unknown; - m_startOrEnd = false; - m_objCollisionList = null; - } - - public int collidertype - { - get { return m_colliderType; } - set { m_colliderType = value; } - } - - public bool startOrEnd - { - get { return m_startOrEnd; } - set { m_startOrEnd = value; } - } - - public void addCollider(uint localID) - { - m_objCollisionList.Add(localID); - } - } - - - public abstract class PhysicsActor - { - public delegate void RequestTerseUpdate(); - - public delegate void CollisionUpdate(EventArgs e); - - public delegate void OutOfBounds(PhysicsVector pos); - -#pragma warning disable 67 - public event PositionUpdate OnPositionUpdate; - public event VelocityUpdate OnVelocityUpdate; - public event OrientationUpdate OnOrientationUpdate; - public event RequestTerseUpdate OnRequestTerseUpdate; - public event CollisionUpdate OnCollisionUpdate; - public event OutOfBounds OnOutOfBounds; -#pragma warning restore 67 - - public static PhysicsActor Null - { - get { return new NullPhysicsActor(); } - } - - public abstract PhysicsVector Size { get; set; } - - public abstract PrimitiveBaseShape Shape { set; } - - public virtual void RequestPhysicsterseUpdate() - { - // Make a temporary copy of the event to avoid possibility of - // a race condition if the last subscriber unsubscribes - // immediately after the null check and before the event is raised. - RequestTerseUpdate handler = OnRequestTerseUpdate; - if (handler != null) - { - OnRequestTerseUpdate(); - } - } - - public virtual void RaiseOutOfBounds(PhysicsVector pos) - { - // Make a temporary copy of the event to avoid possibility of - // a race condition if the last subscriber unsubscribes - // immediately after the null check and before the event is raised. - OutOfBounds handler = OnOutOfBounds; - if (handler != null) - { - OnOutOfBounds(pos); - } - } - - public virtual void SendCollisionUpdate(EventArgs e) - { - // CollisionUpdate handler = OnCollisionUpdate; - if (OnCollisionUpdate != null) - OnCollisionUpdate(e); - } - - - public abstract PhysicsVector Position { get; set; } - - public abstract float Mass { get; } - - public abstract PhysicsVector Force { get; } - - public abstract PhysicsVector GeometricCenter { get; } - - public abstract PhysicsVector CenterOfMass { get; } - - public abstract PhysicsVector Velocity { get; set; } - - public abstract PhysicsVector Acceleration { get; } - - public abstract Quaternion Orientation { get; set; } - public abstract int PhysicsActorType { get; set; } - - public abstract bool IsPhysical { get; set; } - - public abstract bool Flying { get; set; } - public abstract bool SetAlwaysRun { get; set; } - public abstract bool ThrottleUpdates { get; set; } - - public abstract bool IsColliding { get; set; } - public abstract bool CollidingGround { get; set; } - public abstract bool CollidingObj { get; set; } - - public abstract PhysicsVector RotationalVelocity { get; set; } - - public abstract bool Kinematic { get; set; } - - public abstract void AddForce(PhysicsVector force); - - public abstract void SetMomentum(PhysicsVector momentum); - - public virtual void SetCollisionMesh(byte[] vData, string MeshName, bool vbScaleMesh) { } // rex - public virtual void SetBoundsScaling(bool vbScaleMesh) { } // rex - public int NextPrimVolumeTime = 0; // rex - public uint m_localID; // rex - } - - public class NullPhysicsActor : PhysicsActor - { - public override PhysicsVector Position - { - get { return PhysicsVector.Zero; } - set { return; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override PhysicsVector Size - { - get { return PhysicsVector.Zero; } - set { return; } - } - - public override float Mass - { - get { return 0f; } - } - - public override PhysicsVector Force - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override PhysicsVector Velocity - { - get { return PhysicsVector.Zero; } - set { return; } - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { } - } - - public override PhysicsVector Acceleration - { - get { return PhysicsVector.Zero; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool Flying - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool IsColliding - { - get { return false; } - set { return; } - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Unknown; } - set { return; } - } - - public override bool Kinematic - { - get { return true; } - set { return; } - } - - public override void AddForce(PhysicsVector force) - { - return; - } - - public override PhysicsVector RotationalVelocity - { - get { return PhysicsVector.Zero; } - set { return; } - } - - public override void SetMomentum(PhysicsVector momentum) - { - return; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using System.Collections.Generic; +using Axiom.Math; +using OpenSim.Framework; + +namespace OpenSim.Region.Physics.Manager +{ + public delegate void PositionUpdate(PhysicsVector position); + + public delegate void VelocityUpdate(PhysicsVector velocity); + + public delegate void OrientationUpdate(Quaternion orientation); + + public enum ActorTypes : int + { + Unknown = 0, + Agent = 1, + Prim = 2, + Ground = 3, + PrimVolume = 4 // rex + } + + public class CollisionEventUpdate : EventArgs + { + // Raising the event on the object, so don't need to provide location.. further up the tree knows that info. + public int m_colliderType; + public bool m_startOrEnd; + public uint m_LocalID; // rex + public List m_objCollisionList; + + public CollisionEventUpdate(uint localID, int colliderType, bool startOrEnd, List objCollisionList) + { + m_LocalID = localID; // rex + m_colliderType = colliderType; + m_startOrEnd = startOrEnd; + m_objCollisionList = objCollisionList; + } + + public CollisionEventUpdate(bool startOrEnd) + { + m_colliderType = (int) ActorTypes.Unknown; + m_startOrEnd = startOrEnd; + m_objCollisionList = null; + } + + public CollisionEventUpdate() + { + m_colliderType = (int) ActorTypes.Unknown; + m_startOrEnd = false; + m_objCollisionList = null; + } + + public int collidertype + { + get { return m_colliderType; } + set { m_colliderType = value; } + } + + public bool startOrEnd + { + get { return m_startOrEnd; } + set { m_startOrEnd = value; } + } + + public void addCollider(uint localID) + { + m_objCollisionList.Add(localID); + } + } + + + public abstract class PhysicsActor + { + public delegate void RequestTerseUpdate(); + + public delegate void CollisionUpdate(EventArgs e); + + public delegate void OutOfBounds(PhysicsVector pos); + +#pragma warning disable 67 + public event PositionUpdate OnPositionUpdate; + public event VelocityUpdate OnVelocityUpdate; + public event OrientationUpdate OnOrientationUpdate; + public event RequestTerseUpdate OnRequestTerseUpdate; + public event CollisionUpdate OnCollisionUpdate; + public event OutOfBounds OnOutOfBounds; +#pragma warning restore 67 + + public static PhysicsActor Null + { + get { return new NullPhysicsActor(); } + } + + public abstract bool Stopped { get; } + + public abstract PhysicsVector Size { get; set; } + + public abstract PrimitiveBaseShape Shape { set; } + + public abstract bool Grabbed { set; } + + public abstract bool Selected { set; } + + public abstract void CrossingFailure(); + + public virtual void RequestPhysicsterseUpdate() + { + // Make a temporary copy of the event to avoid possibility of + // a race condition if the last subscriber unsubscribes + // immediately after the null check and before the event is raised. + RequestTerseUpdate handler = OnRequestTerseUpdate; + + if (handler != null) + { + + handler(); + + } + } + + public virtual void RaiseOutOfBounds(PhysicsVector pos) + { + // Make a temporary copy of the event to avoid possibility of + // a race condition if the last subscriber unsubscribes + // immediately after the null check and before the event is raised. + OutOfBounds handler = OnOutOfBounds; + if (handler != null) + { + handler(pos); + } + } + + public virtual void SendCollisionUpdate(EventArgs e) + { + CollisionUpdate handler = OnCollisionUpdate; + + if (handler != null) + { + handler(e); + } + + } + + + public abstract PhysicsVector Position { get; set; } + + public abstract float Mass { get; } + + public abstract PhysicsVector Force { get; } + + public abstract PhysicsVector GeometricCenter { get; } + + public abstract PhysicsVector CenterOfMass { get; } + + public abstract PhysicsVector Velocity { get; set; } + + public abstract float CollisionScore { get;} + + public abstract PhysicsVector Acceleration { get; } + + public abstract Quaternion Orientation { get; set; } + public abstract int PhysicsActorType { get; set; } + + public abstract bool IsPhysical { get; set; } + + public abstract bool Flying { get; set; } + public abstract bool SetAlwaysRun { get; set; } + public abstract bool ThrottleUpdates { get; set; } + + public abstract bool IsColliding { get; set; } + public abstract bool CollidingGround { get; set; } + public abstract bool CollidingObj { get; set; } + + public abstract PhysicsVector RotationalVelocity { get; set; } + + public abstract bool Kinematic { get; set; } + + public abstract void AddForce(PhysicsVector force); + + public abstract void SetMomentum(PhysicsVector momentum); + + public virtual void SetCollisionMesh(byte[] vData, string MeshName, bool vbScaleMesh) { } // rex + public virtual void SetBoundsScaling(bool vbScaleMesh) { } // rex + public int NextPrimVolumeTime = 0; // rex + public uint m_localID; // rex + } + + public class NullPhysicsActor : PhysicsActor + { + public override bool Stopped + { + get{ return false; } + } + + public override PhysicsVector Position + { + get { return PhysicsVector.Zero; } + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override PhysicsVector Size + { + get { return PhysicsVector.Zero; } + set { return; } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { return PhysicsVector.Zero; } + set { return; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override void CrossingFailure() + { + + } + + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { } + } + + public override PhysicsVector Acceleration + { + get { return PhysicsVector.Zero; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool IsColliding + { + get { return false; } + set { return; } + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Unknown; } + set { return; } + } + + public override bool Kinematic + { + get { return true; } + set { return; } + } + + public override void AddForce(PhysicsVector force) + { + return; + } + + public override PhysicsVector RotationalVelocity + { + get { return PhysicsVector.Zero; } + set { return; } + } + + public override void SetMomentum(PhysicsVector momentum) + { + return; + } + } +} diff --git a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs index 4d98a8a673..08f04b5c34 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs @@ -1,181 +1,188 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using OpenSim.Framework.Console; - -namespace OpenSim.Region.Physics.Manager -{ - /// - /// Description of MyClass. - /// - public class PhysicsPluginManager - { - private Dictionary _PhysPlugins = new Dictionary(); - private Dictionary _MeshPlugins = new Dictionary(); - - public PhysicsPluginManager() - { - } - - public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName) - { - if (String.IsNullOrEmpty(physEngineName)) - { - return PhysicsScene.Null; - } - - if (String.IsNullOrEmpty(meshEngineName)) - { - return PhysicsScene.Null; - } - - IMesher meshEngine = null; - if (_MeshPlugins.ContainsKey(meshEngineName)) - { - MainLog.Instance.Verbose("PHYSICS", "creating meshing engine " + meshEngineName); - meshEngine = _MeshPlugins[meshEngineName].GetMesher(); - } - else - { - MainLog.Instance.Warn("PHYSICS", "couldn't find meshingEngine: {0}", meshEngineName); - throw new ArgumentException(String.Format("couldn't find meshingEngine: {0}", meshEngineName)); - } - - if (_PhysPlugins.ContainsKey(physEngineName)) - { - MainLog.Instance.Verbose("PHYSICS", "creating " + physEngineName); - PhysicsScene result = _PhysPlugins[physEngineName].GetScene(); - result.Initialise(meshEngine); - return result; - } - else - { - MainLog.Instance.Warn("PHYSICS", "couldn't find physicsEngine: {0}", physEngineName); - throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", physEngineName)); - } - } - - public void LoadPlugins() - { - // Load "plugins", that are hard coded and not existing in form of an external lib - IMeshingPlugin plugHard; - plugHard = new ZeroMesherPlugin(); - _MeshPlugins.Add(plugHard.GetName(), plugHard); - MainLog.Instance.Verbose("PHYSICS", "Added meshing engine: " + plugHard.GetName()); - - // And now walk all assemblies (DLLs effectively) and see if they are home - // of a plugin that is of interest for us - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Physics"); - string[] pluginFiles = Directory.GetFiles(path, "*.dll"); - - for (int i = 0; i < pluginFiles.Length; i++) - { - AddPlugin(pluginFiles[i]); - } - } - - private void AddPlugin(string FileName) +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Physics.Manager +{ + /// + /// Description of MyClass. + /// + public class PhysicsPluginManager + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private Dictionary _PhysPlugins = new Dictionary(); + private Dictionary _MeshPlugins = new Dictionary(); + + public PhysicsPluginManager() { - try - { - Assembly pluginAssembly = Assembly.LoadFrom(FileName); - - foreach (Type pluginType in pluginAssembly.GetTypes()) - { - if (pluginType.IsPublic) - { - if (!pluginType.IsAbstract) - { - Type physTypeInterface = pluginType.GetInterface("IPhysicsPlugin", true); - - if (physTypeInterface != null) - { - IPhysicsPlugin plug = - (IPhysicsPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); - plug.Init(); - _PhysPlugins.Add(plug.GetName(), plug); - MainLog.Instance.Verbose("PHYSICS", "Added physics engine: " + plug.GetName()); - } - - Type meshTypeInterface = pluginType.GetInterface("IMeshingPlugin", true); - - if (meshTypeInterface != null) - { - IMeshingPlugin plug = - (IMeshingPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); - _MeshPlugins.Add(plug.GetName(), plug); - MainLog.Instance.Verbose("PHYSICS", "Added meshing engine: " + plug.GetName()); - } - - physTypeInterface = null; - meshTypeInterface = null; - } - } - } - + } + + public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName) + { + if (String.IsNullOrEmpty(physEngineName)) + { + return PhysicsScene.Null; + } + + if (String.IsNullOrEmpty(meshEngineName)) + { + return PhysicsScene.Null; + } + + IMesher meshEngine = null; + if (_MeshPlugins.ContainsKey(meshEngineName)) + { + m_log.Info("[PHYSICS]: creating meshing engine " + meshEngineName); + meshEngine = _MeshPlugins[meshEngineName].GetMesher(); + } + else + { + m_log.WarnFormat("[PHYSICS]: couldn't find meshingEngine: {0}", meshEngineName); + throw new ArgumentException(String.Format("couldn't find meshingEngine: {0}", meshEngineName)); + } + + if (_PhysPlugins.ContainsKey(physEngineName)) + { + m_log.Info("[PHYSICS]: creating " + physEngineName); + PhysicsScene result = _PhysPlugins[physEngineName].GetScene(); + result.Initialise(meshEngine); + return result; + } + else + { + m_log.WarnFormat("[PHYSICS]: couldn't find physicsEngine: {0}", physEngineName); + throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", physEngineName)); + } + } + + public void LoadPlugins() + { + // Load "plugins", that are hard coded and not existing in form of an external lib + IMeshingPlugin plugHard; + plugHard = new ZeroMesherPlugin(); + _MeshPlugins.Add(plugHard.GetName(), plugHard); + m_log.Info("[PHYSICS]: Added meshing engine: " + plugHard.GetName()); + + // And now walk all assemblies (DLLs effectively) and see if they are home + // of a plugin that is of interest for us + string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Physics"); + string[] pluginFiles = Directory.GetFiles(path, "*.dll"); + + for (int i = 0; i < pluginFiles.Length; i++) + { + AddPlugin(pluginFiles[i]); + } + } + + private void AddPlugin(string FileName) + { + // TODO / NOTE + // The assembly named 'OpenSim.Region.Physics.BasicPhysicsPlugin' was loaded from + // 'file:///C:/OpenSim/trunk2/bin/Physics/OpenSim.Region.Physics.BasicPhysicsPlugin.dll' + // using the LoadFrom context. The use of this context can result in unexpected behavior + // for serialization, casting and dependency resolution. In almost all cases, it is recommended + // that the LoadFrom context be avoided. This can be done by installing assemblies in the + // Global Assembly Cache or in the ApplicationBase directory and using Assembly. + // Load when explicitly loading assemblies. + Assembly pluginAssembly = Assembly.LoadFrom(FileName); + + foreach (Type pluginType in pluginAssembly.GetTypes()) + { + if (pluginType.IsPublic) + { + if (!pluginType.IsAbstract) + { + IPhysicsPlugin plug = + (IPhysicsPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + plug.Init(); + _PhysPlugins.Add(plug.GetName(), plug); + m_log.Info("[PHYSICS]: Added physics engine: " + plug.GetName()); + } + + if (physTypeInterface != null) + { + IPhysicsPlugin plug = + (IPhysicsPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + plug.Init(); + _PhysPlugins.Add(plug.GetName(), plug); + MainLog.Instance.Verbose("PHYSICS", "Added physics engine: " + plug.GetName()); + } + + if (meshTypeInterface != null) + { + IMeshingPlugin plug = + (IMeshingPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); + _MeshPlugins.Add(plug.GetName(), plug); + m_log.Info("[PHYSICS]: Added meshing engine: " + plug.GetName()); + } + } + } + pluginAssembly = null; } catch(Exception e) { MainLog.Instance.Warn("PHYSICS", "Error loading plugin " + FileName + ": " + e.Message); - } - } - - //--- - public static void PhysicsPluginMessage(string message, bool isWarning) - { - if (isWarning) - { - MainLog.Instance.Warn("PHYSICS", message); - } - else - { - MainLog.Instance.Verbose("PHYSICS", message); - } - } - - //--- - } - - public interface IPhysicsPlugin - { - bool Init(); - PhysicsScene GetScene(); - string GetName(); - void Dispose(); - } - - public interface IMeshingPlugin - { - string GetName(); - IMesher GetMesher(); - } -} \ No newline at end of file + } + } + + //--- + public static void PhysicsPluginMessage(string message, bool isWarning) + { + if (isWarning) + { + m_log.Warn("[PHYSICS]: " + message); + } + else + { + m_log.Info("[PHYSICS]: " + message); + } + } + + //--- + } + + public interface IPhysicsPlugin + { + bool Init(); + PhysicsScene GetScene(); + string GetName(); + void Dispose(); + } + + public interface IMeshingPlugin + { + string GetName(); + IMesher GetMesher(); + } +} diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 3c21542c66..67b3f77f64 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -1,160 +1,168 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -using Axiom.Math; -using OpenSim.Framework; -using OpenSim.Framework.Console; - -namespace OpenSim.Region.Physics.Manager -{ - public delegate void physicsCrash(); - - public abstract class PhysicsScene - { - // The only thing that should register for this event is the InnerScene - // Anything else could cause problems. - - public event physicsCrash OnPhysicsCrash; - - public static PhysicsScene Null - { - get { return new NullPhysicsScene(); } - } - - public virtual void TriggerPhysicsBasedRestart() - { - physicsCrash handler = OnPhysicsCrash; - if (handler != null) - { - OnPhysicsCrash(); - } - } - - - public abstract void Initialise(IMesher meshmerizer); - - public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID); // rex, localID added - - public abstract void RemoveAvatar(PhysicsActor actor); - - public abstract void RemovePrim(PhysicsActor prim); - - public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, uint localID); //To be removed, rex, localID added - public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID); // rex, localID added - - public abstract void AddPhysicsActorTaint(PhysicsActor prim); - - public abstract float Simulate(float timeStep); - - public abstract void GetResults(); - - public abstract void SetTerrain(float[] heightMap); - - public abstract void DeleteTerrain(); - - public abstract bool IsThreaded { get; } - - private class NullPhysicsScene : PhysicsScene - { - private static int m_workIndicator; - - - public override void Initialise(IMesher meshmerizer) - { - // Does nothing right now - } - - public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID) - { - MainLog.Instance.Verbose("PHYSICS", "NullPhysicsScene : AddAvatar({0})", position); - return PhysicsActor.Null; - } - - public override void RemoveAvatar(PhysicsActor actor) - { - } - - public override void RemovePrim(PhysicsActor prim) - { - } - -/* - public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) - { - MainLog.Instance.Verbose("NullPhysicsScene : AddPrim({0},{1})", position, size); - return PhysicsActor.Null; - } -*/ - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, uint localID) //To be removed - { - return AddPrimShape(primName, pbs, position, size, rotation, false, localID); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) - { - MainLog.Instance.Verbose("PHYSICS", "NullPhysicsScene : AddPrim({0},{1})", position, size); - return PhysicsActor.Null; - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - m_workIndicator = (m_workIndicator + 1)%10; - - //MainLog.Instance.SetStatus(m_workIndicator.ToString()); - return 0f; - } - - public override void GetResults() - { - MainLog.Instance.Verbose("PHYSICS", "NullPhysicsScene : GetResults()"); - } - - public override void SetTerrain(float[] heightMap) - { - MainLog.Instance.Verbose("PHYSICS", "NullPhysicsScene : SetTerrain({0} items)", heightMap.Length); - } - - public override void DeleteTerrain() - { - } - - public override bool IsThreaded - { - get { return false; } - } - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using Axiom.Math; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Physics.Manager +{ + public delegate void physicsCrash(); + + public abstract class PhysicsScene + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // The only thing that should register for this event is the InnerScene + // Anything else could cause problems. + + public event physicsCrash OnPhysicsCrash; + + public static PhysicsScene Null + { + get { return new NullPhysicsScene(); } + } + + public virtual void TriggerPhysicsBasedRestart() + { + physicsCrash handler = OnPhysicsCrash; + if (handler != null) + { + OnPhysicsCrash(); + } + } + + + public abstract void Initialise(IMesher meshmerizer); + + public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size); + + public abstract void RemoveAvatar(PhysicsActor actor); + + public abstract void RemovePrim(PhysicsActor prim); + + public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, uint localID); //To be removed, rex, localID added + public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID); // rex, localID added + + public abstract void AddPhysicsActorTaint(PhysicsActor prim); + + public abstract float Simulate(float timeStep); + + public abstract void GetResults(); + + public abstract void SetTerrain(float[] heightMap); + + public abstract void DeleteTerrain(); + + public abstract void Dispose(); + + public abstract bool IsThreaded { get; } + + private class NullPhysicsScene : PhysicsScene + { + private static int m_workIndicator; + + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddAvatar({0})", position); + return PhysicsActor.Null; + } + + public override void RemoveAvatar(PhysicsActor actor) + { + } + + public override void RemovePrim(PhysicsActor prim) + { + } + +/* + public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) + { + m_log.InfoFormat("NullPhysicsScene : AddPrim({0},{1})", position, size); + return PhysicsActor.Null; + } +*/ + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, uint localID) //To be removed + { + return AddPrimShape(primName, pbs, position, size, rotation, false, localID); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) + { + m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddPrim({0},{1})", position, size); + return PhysicsActor.Null; + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + m_workIndicator = (m_workIndicator + 1) % 10; + + return 0f; + } + + public override void GetResults() + { + m_log.Info("[PHYSICS]: NullPhysicsScene : GetResults()"); + } + + public override void SetTerrain(float[] heightMap) + { + m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : SetTerrain({0} items)", heightMap.Length); + } + + public override void DeleteTerrain() + { + } + + public override bool IsThreaded + { + get { return false; } + } + public override void Dispose() + { + + } + } + } +} diff --git a/OpenSim/Region/Physics/Manager/PhysicsSensor.cs b/OpenSim/Region/Physics/Manager/PhysicsSensor.cs new file mode 100644 index 0000000000..b85c5b31cb --- /dev/null +++ b/OpenSim/Region/Physics/Manager/PhysicsSensor.cs @@ -0,0 +1,86 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using System.Collections.Generic; +using System.Timers; +using Axiom.Math; +using OpenSim.Framework; + +namespace OpenSim.Region.Physics.Manager +{ + [Flags] + public enum SenseType : uint + { + NONE = 0, + AGENT = 1, + ACTIVE = 2, + PASSIVE = 3, + SCRIPTED = 4 + + } + public abstract class PhysicsSensor + { + + public static PhysicsSensor Null + { + get { return new NullPhysicsSensor(); } + } + public abstract PhysicsVector Position {get; set;} + public abstract void TimerCallback (object obj, ElapsedEventArgs eea); + public abstract float radianarc {get; set;} + public abstract string targetname {get; set;} + public abstract Guid targetKey{get;set;} + public abstract SenseType sensetype { get;set;} + public abstract float range { get;set;} + public abstract float rateSeconds { get;set;} + + + + } + + public class NullPhysicsSensor : PhysicsSensor + { + + public override PhysicsVector Position + { + get { return PhysicsVector.Zero; } + set { return; } + } + public override void TimerCallback(object obj, ElapsedEventArgs eea) + { + // don't do squat + } + public override float radianarc { get { return 0f; } set { } } + public override string targetname { get { return ""; } set { } } + public override Guid targetKey { get { return Guid.Empty; } set { } } + public override SenseType sensetype { get { return SenseType.NONE; } set { } } + public override float range { get { return 0; } set { } } + public override float rateSeconds { get { return 0; } set { } } + + } +} diff --git a/OpenSim/Region/Physics/Manager/PhysicsVector.cs b/OpenSim/Region/Physics/Manager/PhysicsVector.cs index 6194da0b76..d81115b0d3 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsVector.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsVector.cs @@ -1,103 +1,158 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; - -namespace OpenSim.Region.Physics.Manager -{ - public class PhysicsVector - { - public float X; - public float Y; - public float Z; - - public PhysicsVector() - { - } - - public PhysicsVector(float x, float y, float z) - { - X = x; - Y = y; - Z = z; - } - - public static readonly PhysicsVector Zero = new PhysicsVector(0f, 0f, 0f); - - public override string ToString() - { - return "<" + X + "," + Y + "," + Z + ">"; - } - - // Operations - public static PhysicsVector operator +(PhysicsVector a, PhysicsVector b) - { - return new PhysicsVector(a.X + b.X, a.Y + b.Y, a.Z + b.Z); - } - - public static PhysicsVector operator -(PhysicsVector a, PhysicsVector b) - { - return new PhysicsVector(a.X - b.X, a.Y - b.Y, a.Z - b.Z); - } - - public static PhysicsVector cross(PhysicsVector a, PhysicsVector b) - { - return new PhysicsVector(a.Y*b.Z - a.Z*b.Y, a.Z*b.X - a.X*b.Z, a.X*b.Y - a.Y*b.X); - } - - public float length() - { - return (float) Math.Sqrt(X*X + Y*Y + Z*Z); - } - - public static PhysicsVector operator /(PhysicsVector v, float f) - { - return new PhysicsVector(v.X/f, v.Y/f, v.Z/f); - } - - public static PhysicsVector operator *(PhysicsVector v, float f) - { - return new PhysicsVector(v.X*f, v.Y*f, v.Z*f); - } - - public static PhysicsVector operator *(float f, PhysicsVector v) - { - return v*f; - } - - public virtual bool IsIdentical(PhysicsVector v, float tolerance) - { - PhysicsVector diff = this - v; - float d = diff.length(); - if (d < tolerance) - return true; - - return false; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; + +namespace OpenSim.Region.Physics.Manager +{ + public class PhysicsVector + { + public float X; + public float Y; + public float Z; + + public PhysicsVector() + { + } + + public PhysicsVector(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + public void setValues(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + public static readonly PhysicsVector Zero = new PhysicsVector(0f, 0f, 0f); + + public override string ToString() + { + return "<" + X + "," + Y + "," + Z + ">"; + } + + /// + /// These routines are the easiest way to store XYZ values in an LLVector3 without requiring 3 calls. + /// + /// + public byte[] GetBytes() + { + byte[] byteArray = new byte[12]; + + Buffer.BlockCopy(BitConverter.GetBytes(X), 0, byteArray, 0, 4); + Buffer.BlockCopy(BitConverter.GetBytes(Y), 0, byteArray, 4, 4); + Buffer.BlockCopy(BitConverter.GetBytes(Z), 0, byteArray, 8, 4); + + if (!BitConverter.IsLittleEndian) + { + Array.Reverse(byteArray, 0, 4); + Array.Reverse(byteArray, 4, 4); + Array.Reverse(byteArray, 8, 4); + } + + return byteArray; + } + + public void FromBytes(byte[] byteArray, int pos) + { + byte[] conversionBuffer = null; + if (!BitConverter.IsLittleEndian) + { + // Big endian architecture + if (conversionBuffer == null) + conversionBuffer = new byte[12]; + + Buffer.BlockCopy(byteArray, pos, conversionBuffer, 0, 12); + + Array.Reverse(conversionBuffer, 0, 4); + Array.Reverse(conversionBuffer, 4, 4); + Array.Reverse(conversionBuffer, 8, 4); + + X = BitConverter.ToSingle(conversionBuffer, 0); + Y = BitConverter.ToSingle(conversionBuffer, 4); + Z = BitConverter.ToSingle(conversionBuffer, 8); + } + else + { + // Little endian architecture + X = BitConverter.ToSingle(byteArray, pos); + Y = BitConverter.ToSingle(byteArray, pos + 4); + Z = BitConverter.ToSingle(byteArray, pos + 8); + } + } + + // Operations + public static PhysicsVector operator +(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.X + b.X, a.Y + b.Y, a.Z + b.Z); + } + + public static PhysicsVector operator -(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.X - b.X, a.Y - b.Y, a.Z - b.Z); + } + + public static PhysicsVector cross(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.Y*b.Z - a.Z*b.Y, a.Z*b.X - a.X*b.Z, a.X*b.Y - a.Y*b.X); + } + + public float length() + { + return (float) Math.Sqrt(X*X + Y*Y + Z*Z); + } + + public static PhysicsVector operator /(PhysicsVector v, float f) + { + return new PhysicsVector(v.X/f, v.Y/f, v.Z/f); + } + + public static PhysicsVector operator *(PhysicsVector v, float f) + { + return new PhysicsVector(v.X*f, v.Y*f, v.Z*f); + } + + public static PhysicsVector operator *(float f, PhysicsVector v) + { + return v*f; + } + + public virtual bool IsIdentical(PhysicsVector v, float tolerance) + { + PhysicsVector diff = this - v; + float d = diff.length(); + if (d < tolerance) + return true; + + return false; + } + } +} diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs index 63aab34fd7..da19b95247 100644 --- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs +++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs @@ -1,69 +1,69 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using OpenSim.Framework; - -/* - * This is the zero mesher. - * Whatever you want him to mesh, he can't, telling you that by responding with a null pointer. - * Effectivly this is for switching off meshing and for testing as each physics machine should deal - * with the null pointer situation. - * But it's also a convenience thing, as physics machines can rely on having a mesher in any situation, even - * if it's a dump one like this. - * Note, that this mesher is *not* living in a module but in the manager itself, so - * it's always availabe and thus the default in case of configuration errors -*/ - -namespace OpenSim.Region.Physics.Manager -{ - public class ZeroMesherPlugin : IMeshingPlugin - { - public ZeroMesherPlugin() - { - } - - public string GetName() - { - return "ZeroMesher"; - } - - public IMesher GetMesher() - { - return new ZeroMesher(); - } - } - - public class ZeroMesher : IMesher - { - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) - { - return null; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using OpenSim.Framework; + +/* + * This is the zero mesher. + * Whatever you want him to mesh, he can't, telling you that by responding with a null pointer. + * Effectivly this is for switching off meshing and for testing as each physics machine should deal + * with the null pointer situation. + * But it's also a convenience thing, as physics machines can rely on having a mesher in any situation, even + * if it's a dump one like this. + * Note, that this mesher is *not* living in a module but in the manager itself, so + * it's always availabe and thus the default in case of configuration errors +*/ + +namespace OpenSim.Region.Physics.Manager +{ + public class ZeroMesherPlugin : IMeshingPlugin + { + public ZeroMesherPlugin() + { + } + + public string GetName() + { + return "ZeroMesher"; + } + + public IMesher GetMesher() + { + return new ZeroMesher(); + } + } + + public class ZeroMesher : IMesher + { + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + { + return null; + } + } +} diff --git a/OpenSim/Region/Physics/Meshing/Extruder.cs b/OpenSim/Region/Physics/Meshing/Extruder.cs index ab065d15ba..7fe6bd69ef 100644 --- a/OpenSim/Region/Physics/Meshing/Extruder.cs +++ b/OpenSim/Region/Physics/Meshing/Extruder.cs @@ -1,110 +1,125 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.Meshing -{ - internal class Extruder - { - public float startParameter; - public float stopParameter; - public PhysicsVector size; - - public Mesh Extrude(Mesh m) - { - // Currently only works for iSteps=1; - Mesh result = new Mesh(); - - Mesh workingPlus = m.Clone(); - Mesh workingMinus = m.Clone(); - - foreach (Vertex v in workingPlus.vertices) - { - if (v == null) - continue; - - v.Z = +.5f; - v.X *= size.X; - v.Y *= size.Y; - v.Z *= size.Z; - } - - foreach (Vertex v in workingMinus.vertices) - { - if (v == null) - continue; - - v.Z = -.5f; - v.X *= size.X; - v.Y *= size.Y; - v.Z *= size.Z; - } - - foreach (Triangle t in workingMinus.triangles) - { - t.invertNormal(); - } - - result.Append(workingMinus); - result.Append(workingPlus); - - int iLastNull = 0; - for (int i = 0; i < workingPlus.vertices.Count; i++) - { - int iNext = (i + 1); - - if (workingPlus.vertices[i] == null) // Can't make a simplex here - { - iLastNull = i + 1; - continue; - } - - if (i == workingPlus.vertices.Count - 1) // End of list - { - iNext = iLastNull; - } - - if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment - { - iNext = iLastNull; - } - - Triangle tSide; - tSide = new Triangle(workingPlus.vertices[i], workingMinus.vertices[i], workingPlus.vertices[iNext]); - result.Add(tSide); - - tSide = - new Triangle(workingPlus.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]); - result.Add(tSide); - } - - return result; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + internal class Extruder + { + public float startParameter; + public float stopParameter; + public PhysicsVector size; + + public float taperTopFactorX = 1f; + public float taperTopFactorY = 1f; + public float taperBotFactorX = 1f; + public float taperBotFactorY = 1f; + public float pushX = 0f; + public float pushY = 0f; + + public Mesh Extrude(Mesh m) + { + // Currently only works for iSteps=1; + Mesh result = new Mesh(); + + Mesh workingPlus = m.Clone(); + Mesh workingMinus = m.Clone(); + + foreach (Vertex v in workingPlus.vertices) + { + if (v == null) + continue; + + // This is the top + // Set the Z + .5 to match the rest of the scale of the mesh + // Scale it by Size, and Taper the scaling + v.Z = +.5f; + v.X *= (size.X * taperTopFactorX); + v.Y *= (size.Y * taperTopFactorY); + v.Z *= size.Z; + + //Push the top of the object over by the Top Shear amount + v.X += pushX * size.X; + v.Y += pushY * size.X; + } + + foreach (Vertex v in workingMinus.vertices) + { + if (v == null) + continue; + + // This is the bottom + v.Z = -.5f; + v.X *= (size.X * taperBotFactorX); + v.Y *= (size.Y * taperBotFactorY); + v.Z *= size.Z; + } + + foreach (Triangle t in workingMinus.triangles) + { + t.invertNormal(); + } + + result.Append(workingMinus); + result.Append(workingPlus); + + int iLastNull = 0; + for (int i = 0; i < workingPlus.vertices.Count; i++) + { + int iNext = (i + 1); + + if (workingPlus.vertices[i] == null) // Can't make a simplex here + { + iLastNull = i + 1; + continue; + } + + if (i == workingPlus.vertices.Count - 1) // End of list + { + iNext = iLastNull; + } + + if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment + { + iNext = iLastNull; + } + + Triangle tSide; + tSide = new Triangle(workingPlus.vertices[i], workingMinus.vertices[i], workingPlus.vertices[iNext]); + result.Add(tSide); + + tSide = + new Triangle(workingPlus.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]); + result.Add(tSide); + } + + return result; + } + } +} diff --git a/OpenSim/Region/Physics/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/Meshing/HelperTypes.cs index a5988ae85d..6aebaad3b6 100644 --- a/OpenSim/Region/Physics/Meshing/HelperTypes.cs +++ b/OpenSim/Region/Physics/Meshing/HelperTypes.cs @@ -1,304 +1,304 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.Meshing; - -public class Vertex : PhysicsVector, IComparable -{ - public Vertex(float x, float y, float z) - : base(x, y, z) - { - } - - public Vertex(PhysicsVector v) - : base(v.X, v.Y, v.Z) - { - } - - public Vertex Clone() - { - return new Vertex(X, Y, Z); - } - - public static Vertex FromAngle(double angle) - { - return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f); - } - - - public virtual bool Equals(Vertex v, float tolerance) - { - PhysicsVector diff = this - v; - float d = diff.length(); - if (d < tolerance) - return true; - - return false; - } - - - public int CompareTo(Vertex other) - { - if (X < other.X) - return -1; - - if (X > other.X) - return 1; - - if (Y < other.Y) - return -1; - - if (Y > other.Y) - return 1; - - if (Z < other.Z) - return -1; - - if (Z > other.Z) - return 1; - - return 0; - } - - public static bool operator >(Vertex me, Vertex other) - { - return me.CompareTo(other) > 0; - } - - public static bool operator <(Vertex me, Vertex other) - { - return me.CompareTo(other) < 0; - } - - public String ToRaw() - { - // Why this stuff with the number formatter? - // Well, the raw format uses the english/US notation of numbers - // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1. - // The german notation uses these characters exactly vice versa! - // The Float.ToString() routine is a localized one, giving different results depending on the country - // settings your machine works with. Unusable for a machine readable file format :-( - NumberFormatInfo nfi = new NumberFormatInfo(); - nfi.NumberDecimalSeparator = "."; - nfi.NumberDecimalDigits = 3; - - String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi); - - return s1; - } -} - -public class Triangle -{ - public Vertex v1; - public Vertex v2; - public Vertex v3; - - private float radius_square; - private float cx; - private float cy; - - public Triangle(Vertex _v1, Vertex _v2, Vertex _v3) - { - v1 = _v1; - v2 = _v2; - v3 = _v3; - - CalcCircle(); - } - - public bool isInCircle(float x, float y) - { - float dx, dy; - float dd; - - dx = x - cx; - dy = y - cy; - - dd = dx*dx + dy*dy; - if (dd < radius_square) - return true; - else - return false; - } - - public bool isDegraded() - { - // This means, the vertices of this triangle are somewhat strange. - // They either line up or at least two of them are identical - return (radius_square == 0.0); - } - - private void CalcCircle() - { - // Calculate the center and the radius of a circle given by three points p1, p2, p3 - // It is assumed, that the triangles vertices are already set correctly - double p1x, p2x, p1y, p2y, p3x, p3y; - - // Deviation of this routine: - // A circle has the general equation (M-p)^2=r^2, where M and p are vectors - // this gives us three equations f(p)=r^2, each for one point p1, p2, p3 - // putting respectively two equations together gives two equations - // f(p1)=f(p2) and f(p1)=f(p3) - // bringing all constant terms to one side brings them to the form - // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors) - // and c1, c2 are scalars (Naming conventions like the variables below) - // Now using the equations that are formed by the components of the vectors - // and isolate Mx lets you make one equation that only holds My - // The rest is straight forward and eaasy :-) - // - - /* helping variables for temporary results */ - double c1, c2; - double v1x, v1y, v2x, v2y; - - double z, n; - - double rx, ry; - - // Readout the three points, the triangle consists of - p1x = v1.X; - p1y = v1.Y; - - p2x = v2.X; - p2y = v2.Y; - - p3x = v3.X; - p3y = v3.Y; - - /* calc helping values first */ - c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2; - c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2; - - v1x = p1x - p2x; - v1y = p1y - p2y; - - v2x = p1x - p3x; - v2y = p1y - p3y; - - z = (c1*v2x - c2*v1x); - n = (v1y*v2x - v2y*v1x); - - if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location - { - radius_square = 0.0f; - return; - } - - cy = (float) (z/n); - - if (v2x != 0.0) - { - cx = (float) ((c2 - v2y*cy)/v2x); - } - else if (v1x != 0.0) - { - cx = (float) ((c1 - v1y*cy)/v1x); - } - else - { - Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */ - } - - rx = (p1x - cx); - ry = (p1y - cy); - - radius_square = (float) (rx*rx + ry*ry); - } - - public List GetSimplices() - { - List result = new List(); - Simplex s1 = new Simplex(v1, v2); - Simplex s2 = new Simplex(v2, v3); - Simplex s3 = new Simplex(v3, v1); - - result.Add(s1); - result.Add(s2); - result.Add(s3); - - return result; - } - - public override String ToString() - { - NumberFormatInfo nfi = new NumberFormatInfo(); - nfi.CurrencyDecimalDigits = 2; - nfi.CurrencyDecimalSeparator = "."; - - String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">"; - String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">"; - String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">"; - - return s1 + ";" + s2 + ";" + s3; - } - - public PhysicsVector getNormal() - { - // Vertices - - // Vectors for edges - PhysicsVector e1; - PhysicsVector e2; - - e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); - e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z); - - // Cross product for normal - PhysicsVector n = PhysicsVector.cross(e1, e2); - - // Length - float l = n.length(); - - // Normalized "normal" - n = n/l; - - return n; - } - - public void invertNormal() - { - Vertex vt; - vt = v1; - v1 = v2; - v2 = vt; - } - - // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and - // debugging purposes - public String ToStringRaw() - { - String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw(); - return output; - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Physics.Meshing; + +public class Vertex : PhysicsVector, IComparable +{ + public Vertex(float x, float y, float z) + : base(x, y, z) + { + } + + public Vertex(PhysicsVector v) + : base(v.X, v.Y, v.Z) + { + } + + public Vertex Clone() + { + return new Vertex(X, Y, Z); + } + + public static Vertex FromAngle(double angle) + { + return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f); + } + + + public virtual bool Equals(Vertex v, float tolerance) + { + PhysicsVector diff = this - v; + float d = diff.length(); + if (d < tolerance) + return true; + + return false; + } + + + public int CompareTo(Vertex other) + { + if (X < other.X) + return -1; + + if (X > other.X) + return 1; + + if (Y < other.Y) + return -1; + + if (Y > other.Y) + return 1; + + if (Z < other.Z) + return -1; + + if (Z > other.Z) + return 1; + + return 0; + } + + public static bool operator >(Vertex me, Vertex other) + { + return me.CompareTo(other) > 0; + } + + public static bool operator <(Vertex me, Vertex other) + { + return me.CompareTo(other) < 0; + } + + public String ToRaw() + { + // Why this stuff with the number formatter? + // Well, the raw format uses the english/US notation of numbers + // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1. + // The german notation uses these characters exactly vice versa! + // The Float.ToString() routine is a localized one, giving different results depending on the country + // settings your machine works with. Unusable for a machine readable file format :-( + NumberFormatInfo nfi = new NumberFormatInfo(); + nfi.NumberDecimalSeparator = "."; + nfi.NumberDecimalDigits = 3; + + String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi); + + return s1; + } +} + +public class Triangle +{ + public Vertex v1; + public Vertex v2; + public Vertex v3; + + private float radius_square; + private float cx; + private float cy; + + public Triangle(Vertex _v1, Vertex _v2, Vertex _v3) + { + v1 = _v1; + v2 = _v2; + v3 = _v3; + + CalcCircle(); + } + + public bool isInCircle(float x, float y) + { + float dx, dy; + float dd; + + dx = x - cx; + dy = y - cy; + + dd = dx*dx + dy*dy; + if (dd < radius_square) + return true; + else + return false; + } + + public bool isDegraded() + { + // This means, the vertices of this triangle are somewhat strange. + // They either line up or at least two of them are identical + return (radius_square == 0.0); + } + + private void CalcCircle() + { + // Calculate the center and the radius of a circle given by three points p1, p2, p3 + // It is assumed, that the triangles vertices are already set correctly + double p1x, p2x, p1y, p2y, p3x, p3y; + + // Deviation of this routine: + // A circle has the general equation (M-p)^2=r^2, where M and p are vectors + // this gives us three equations f(p)=r^2, each for one point p1, p2, p3 + // putting respectively two equations together gives two equations + // f(p1)=f(p2) and f(p1)=f(p3) + // bringing all constant terms to one side brings them to the form + // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors) + // and c1, c2 are scalars (Naming conventions like the variables below) + // Now using the equations that are formed by the components of the vectors + // and isolate Mx lets you make one equation that only holds My + // The rest is straight forward and eaasy :-) + // + + /* helping variables for temporary results */ + double c1, c2; + double v1x, v1y, v2x, v2y; + + double z, n; + + double rx, ry; + + // Readout the three points, the triangle consists of + p1x = v1.X; + p1y = v1.Y; + + p2x = v2.X; + p2y = v2.Y; + + p3x = v3.X; + p3y = v3.Y; + + /* calc helping values first */ + c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2; + c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2; + + v1x = p1x - p2x; + v1y = p1y - p2y; + + v2x = p1x - p3x; + v2y = p1y - p3y; + + z = (c1*v2x - c2*v1x); + n = (v1y*v2x - v2y*v1x); + + if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location + { + radius_square = 0.0f; + return; + } + + cy = (float) (z/n); + + if (v2x != 0.0) + { + cx = (float) ((c2 - v2y*cy)/v2x); + } + else if (v1x != 0.0) + { + cx = (float) ((c1 - v1y*cy)/v1x); + } + else + { + Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */ + } + + rx = (p1x - cx); + ry = (p1y - cy); + + radius_square = (float) (rx*rx + ry*ry); + } + + public List GetSimplices() + { + List result = new List(); + Simplex s1 = new Simplex(v1, v2); + Simplex s2 = new Simplex(v2, v3); + Simplex s3 = new Simplex(v3, v1); + + result.Add(s1); + result.Add(s2); + result.Add(s3); + + return result; + } + + public override String ToString() + { + NumberFormatInfo nfi = new NumberFormatInfo(); + nfi.CurrencyDecimalDigits = 2; + nfi.CurrencyDecimalSeparator = "."; + + String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">"; + String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">"; + String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">"; + + return s1 + ";" + s2 + ";" + s3; + } + + public PhysicsVector getNormal() + { + // Vertices + + // Vectors for edges + PhysicsVector e1; + PhysicsVector e2; + + e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); + e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z); + + // Cross product for normal + PhysicsVector n = PhysicsVector.cross(e1, e2); + + // Length + float l = n.length(); + + // Normalized "normal" + n = n/l; + + return n; + } + + public void invertNormal() + { + Vertex vt; + vt = v1; + v1 = v2; + v2 = vt; + } + + // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and + // debugging purposes + public String ToStringRaw() + { + String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw(); + return output; + } +} diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index cd013ea2c6..30fab39976 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -1,389 +1,1081 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenSim.Framework.Console; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.Meshing -{ - public class MeshmerizerPlugin : IMeshingPlugin - { - public MeshmerizerPlugin() - { - } - - public string GetName() - { - return "Meshmerizer"; - } - - public IMesher GetMesher() - { - return new Meshmerizer(); - } - } - - public class Meshmerizer : IMesher - { - // Setting baseDir to a path will enable the dumping of raw files - // raw files can be imported by blender so a visual inspection of the results can be done - // const string baseDir = "rawFiles"; - private const string baseDir = null; - - private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, - PhysicsVector r2, ref float lambda, ref float mu) - { - // p1, p2, points on the straight - // r1, r2, directional vectors of the straight. Not necessarily of length 1! - // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, - // thus allowing to decide whether an intersection is between two points - - float r1x = r1.X; - float r1y = r1.Y; - float r2x = r2.X; - float r2y = r2.Y; - - float denom = r1y*r2x - r1x*r2y; - - if (denom == 0.0) - { - lambda = Single.NaN; - mu = Single.NaN; - return; - } - - float p1x = p1.X; - float p1y = p1.Y; - float p2x = p2.X; - float p2y = p2.Y; - lambda = (-p2x*r2y + p1x*r2y + (p2y - p1y)*r2x)/denom; - mu = (-p2x*r1y + p1x*r1y + (p2y - p1y)*r1x)/denom; - } - - private static List FindInfluencedTriangles(List triangles, Vertex v) - { - List influenced = new List(); - foreach (Triangle t in triangles) - { - if (t.isInCircle(v.X, v.Y)) - { - influenced.Add(t); - } - } - return influenced; - } - - - private static void InsertVertices(List vertices, int usedForSeed, List triangles) - { - // This is a variant of the delaunay algorithm - // each time a new vertex is inserted, all triangles that are influenced by it are deleted - // and replaced by new ones including the new vertex - // It is not very time efficient but easy to implement. - - int iCurrentVertex; - int iMaxVertex = vertices.Count; - for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++) - { - // Background: A triangle mesh fulfills the delaunay condition if (iff!) - // each circumlocutory circle (i.e. the circle that touches all three corners) - // of each triangle is empty of other vertices. - // Obviously a single (seeding) triangle fulfills this condition. - // If we now add one vertex, we need to reconstruct all triangles, that - // do not fulfill this condition with respect to the new triangle - - // Find the triangles that are influenced by the new vertex - Vertex v = vertices[iCurrentVertex]; - if (v == null) - continue; // Null is polygon stop marker. Ignore it - List influencedTriangles = FindInfluencedTriangles(triangles, v); - - List simplices = new List(); - - // Reconstruction phase. First step, dissolve each triangle into it's simplices, - // i.e. it's "border lines" - // Goal is to find "inner" borders and delete them, while the hull gets conserved. - // Inner borders are special in the way that they always come twice, which is how we detect them - foreach (Triangle t in influencedTriangles) - { - List newSimplices = t.GetSimplices(); - simplices.AddRange(newSimplices); - triangles.Remove(t); - } - // Now sort the simplices. That will make identical ones reside side by side in the list - simplices.Sort(); - - // Look for duplicate simplices here. - // Remember, they are directly side by side in the list right now, - // So we only check directly neighbours - int iSimplex; - List innerSimplices = new List(); - for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards - { - if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0) - { - innerSimplices.Add(simplices[iSimplex - 1]); - innerSimplices.Add(simplices[iSimplex]); - } - } - - foreach (Simplex s in innerSimplices) - { - simplices.Remove(s); - } - - // each simplex still in the list belongs to the hull of the region in question - // The new vertex (yes, we still deal with verices here :-) ) forms a triangle - // with each of these simplices. Build the new triangles and add them to the list - foreach (Simplex s in simplices) - { - Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); - if (!t.isDegraded()) - { - triangles.Add(t); - } - } - } - } - - - private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) - // Builds the z (+ and -) surfaces of a box shaped prim - { - UInt16 hollowFactor = primShape.ProfileHollow; - UInt16 profileBegin = primShape.ProfileBegin; - UInt16 profileEnd = primShape.ProfileEnd; - - // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface - // of a block are basically the same - // They may be warped differently but the shape is identical - // So we only create one surface as a model and derive both plus and minus surface of the block from it - // This is done in a model space where the block spans from -.5 to +.5 in X and Y - // The mapping to Scene space is done later during the "extrusion" phase - - // Base - Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f); - Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f); - Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f); - Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f); - - SimpleHull outerHull = new SimpleHull(); - outerHull.AddVertex(MM); - outerHull.AddVertex(PM); - outerHull.AddVertex(PP); - outerHull.AddVertex(MP); - - // Deal with cuts now - if ((profileBegin != 0) || (profileEnd != 0)) - { - double fProfileBeginAngle = profileBegin/50000.0*360.0; - // In degree, for easier debugging and understanding - fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y - double fProfileEndAngle = 360.0 - profileEnd/50000.0*360.0; // Pathend comes as complement to 1.0 - fProfileEndAngle -= (90.0 + 45.0); - if (fProfileBeginAngle < fProfileEndAngle) - fProfileEndAngle -= 360.0; - - // Note, that we don't want to cut out a triangle, even if this is a - // good approximation for small cuts. Indeed we want to cut out an arc - // and we approximate this arc by a polygon chain - // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space - // So it can easily be subtracted from the outer hull - int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5); - // how many steps do we need with approximately 45 degree - double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps; - - Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); - - // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull - SimpleHull cutHull = new SimpleHull(); - cutHull.AddVertex(origin); - for (int i = 0; i < iSteps; i++) - { - double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!! - Vertex v = Vertex.FromAngle(angle*Math.PI/180.0); - cutHull.AddVertex(v); - } - Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0); - // Calculated separately to avoid errors - cutHull.AddVertex(legEnd); - - MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName); - SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); - - outerHull = cuttedHull; - } - - // Deal with the hole here - if (hollowFactor > 0) - { - float hollowFactorF = (float) hollowFactor/(float) 50000; - Vertex IMM = new Vertex(-0.5f*hollowFactorF, -0.5f*hollowFactorF, 0.0f); - Vertex IPM = new Vertex(+0.5f*hollowFactorF, -0.5f*hollowFactorF, 0.0f); - Vertex IMP = new Vertex(-0.5f*hollowFactorF, +0.5f*hollowFactorF, 0.0f); - Vertex IPP = new Vertex(+0.5f*hollowFactorF, +0.5f*hollowFactorF, 0.0f); - - SimpleHull holeHull = new SimpleHull(); - - holeHull.AddVertex(IMM); - holeHull.AddVertex(IMP); - holeHull.AddVertex(IPP); - holeHull.AddVertex(IPM); - - SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); - - outerHull = hollowedHull; - } - - Mesh m = new Mesh(); - - Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); - Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); - Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); - - m.Add(Seed1); - m.Add(Seed2); - m.Add(Seed3); - - m.Add(new Triangle(Seed1, Seed2, Seed3)); - m.Add(outerHull.getVertices()); - - InsertVertices(m.vertices, 3, m.triangles); - m.DumpRaw(baseDir, primName, "Proto first Mesh"); - - m.Remove(Seed1); - m.Remove(Seed2); - m.Remove(Seed3); - m.DumpRaw(baseDir, primName, "Proto seeds removed"); - - m.RemoveTrianglesOutside(outerHull); - m.DumpRaw(baseDir, primName, "Proto outsides removed"); - - foreach (Triangle t in m.triangles) - { - PhysicsVector n = t.getNormal(); - if (n.Z < 0.0) - t.invertNormal(); - } - - Extruder extr = new Extruder(); - - extr.size = size; - - Mesh result = extr.Extrude(m); - result.DumpRaw(baseDir, primName, "Z extruded"); - return result; - } - - public static void CalcNormals(Mesh mesh) - { - int iTriangles = mesh.triangles.Count; - - mesh.normals = new float[iTriangles*3]; - - int i = 0; - foreach (Triangle t in mesh.triangles) - { - float ux, uy, uz; - float vx, vy, vz; - float wx, wy, wz; - - ux = t.v1.X; - uy = t.v1.Y; - uz = t.v1.Z; - - vx = t.v2.X; - vy = t.v2.Y; - vz = t.v2.Z; - - wx = t.v3.X; - wy = t.v3.Y; - wz = t.v3.Z; - - - // Vectors for edges - float e1x, e1y, e1z; - float e2x, e2y, e2z; - - e1x = ux - vx; - e1y = uy - vy; - e1z = uz - vz; - - e2x = ux - wx; - e2y = uy - wy; - e2z = uz - wz; - - - // Cross product for normal - float nx, ny, nz; - nx = e1y*e2z - e1z*e2y; - ny = e1z*e2x - e1x*e2z; - nz = e1x*e2y - e1y*e2x; - - // Length - float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz); - - // Normalized "normal" - nx /= l; - ny /= l; - nz /= l; - - mesh.normals[i] = nx; - mesh.normals[i + 1] = ny; - mesh.normals[i + 2] = nz; - - i += 3; - } - } - - public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) - { - Mesh mesh = null; - - switch (primShape.ProfileShape) - { - case ProfileShape.Square: - mesh = CreateBoxMesh(primName, primShape, size); - CalcNormals(mesh); - break; - default: - mesh = CreateBoxMesh(primName, primShape, size); - CalcNormals(mesh); - //Set default mesh to cube otherwise it'll return - // null and crash on the 'setMesh' method in the physics plugins. - //mesh = null; - break; - } - - return mesh; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + public class MeshmerizerPlugin : IMeshingPlugin + { + public MeshmerizerPlugin() + { + } + + public string GetName() + { + return "Meshmerizer"; + } + + public IMesher GetMesher() + { + return new Meshmerizer(); + } + } + + public class Meshmerizer : IMesher + { + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Setting baseDir to a path will enable the dumping of raw files + // raw files can be imported by blender so a visual inspection of the results can be done + // const string baseDir = "rawFiles"; + private const string baseDir = null; //"rawFiles"; + + private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, + PhysicsVector r2, ref float lambda, ref float mu) + { + // p1, p2, points on the straight + // r1, r2, directional vectors of the straight. Not necessarily of length 1! + // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, + // thus allowing to decide whether an intersection is between two points + + float r1x = r1.X; + float r1y = r1.Y; + float r2x = r2.X; + float r2y = r2.Y; + + float denom = r1y*r2x - r1x*r2y; + + if (denom == 0.0) + { + lambda = Single.NaN; + mu = Single.NaN; + return; + } + + float p1x = p1.X; + float p1y = p1.Y; + float p2x = p2.X; + float p2y = p2.Y; + lambda = (-p2x*r2y + p1x*r2y + (p2y - p1y)*r2x)/denom; + mu = (-p2x*r1y + p1x*r1y + (p2y - p1y)*r1x)/denom; + } + + private static List FindInfluencedTriangles(List triangles, Vertex v) + { + List influenced = new List(); + foreach (Triangle t in triangles) + { + if (t.isInCircle(v.X, v.Y)) + { + influenced.Add(t); + } + } + return influenced; + } + + private static void InsertVertices(List vertices, int usedForSeed, List triangles) + { + // This is a variant of the delaunay algorithm + // each time a new vertex is inserted, all triangles that are influenced by it are deleted + // and replaced by new ones including the new vertex + // It is not very time efficient but easy to implement. + + int iCurrentVertex; + int iMaxVertex = vertices.Count; + for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++) + { + // Background: A triangle mesh fulfills the delaunay condition if (iff!) + // each circumlocutory circle (i.e. the circle that touches all three corners) + // of each triangle is empty of other vertices. + // Obviously a single (seeding) triangle fulfills this condition. + // If we now add one vertex, we need to reconstruct all triangles, that + // do not fulfill this condition with respect to the new triangle + + // Find the triangles that are influenced by the new vertex + Vertex v = vertices[iCurrentVertex]; + if (v == null) + continue; // Null is polygon stop marker. Ignore it + List influencedTriangles = FindInfluencedTriangles(triangles, v); + + List simplices = new List(); + + // Reconstruction phase. First step, dissolve each triangle into it's simplices, + // i.e. it's "border lines" + // Goal is to find "inner" borders and delete them, while the hull gets conserved. + // Inner borders are special in the way that they always come twice, which is how we detect them + foreach (Triangle t in influencedTriangles) + { + List newSimplices = t.GetSimplices(); + simplices.AddRange(newSimplices); + triangles.Remove(t); + } + // Now sort the simplices. That will make identical ones reside side by side in the list + simplices.Sort(); + + // Look for duplicate simplices here. + // Remember, they are directly side by side in the list right now, + // So we only check directly neighbours + int iSimplex; + List innerSimplices = new List(); + for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards + { + if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0) + { + innerSimplices.Add(simplices[iSimplex - 1]); + innerSimplices.Add(simplices[iSimplex]); + } + } + + foreach (Simplex s in innerSimplices) + { + simplices.Remove(s); + } + + // each simplex still in the list belongs to the hull of the region in question + // The new vertex (yes, we still deal with verices here :-) ) forms a triangle + // with each of these simplices. Build the new triangles and add them to the list + foreach (Simplex s in simplices) + { + Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); + if (!t.isDegraded()) + { + triangles.Add(t); + } + } + } + } + + private static SimpleHull BuildHoleHull(PrimitiveBaseShape pbs, ProfileShape pshape, HollowShape hshape, UInt16 hollowFactor) + { + // Tackle HollowShape.Same + float fhollowFactor = (float)hollowFactor; + + switch (pshape) + { + case ProfileShape.Square: + if (hshape == HollowShape.Same) + hshape= HollowShape.Square; + break; + case ProfileShape.EquilateralTriangle: + fhollowFactor = ((float)hollowFactor / 1.9f); + if (hshape == HollowShape.Same) + { + hshape = HollowShape.Triangle; + } + + break; + + case ProfileShape.Circle: + if (pbs.PathCurve == (byte)Extrusion.Straight) + { + if (hshape == HollowShape.Same) + { + hshape = HollowShape.Circle; + } + } + break; + default: + if (hshape == HollowShape.Same) + hshape= HollowShape.Square; + break; + } + + + SimpleHull holeHull = null; + + if (hshape == HollowShape.Square) + { + float hollowFactorF = (float)fhollowFactor / (float)50000; + Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); + Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); + Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); + Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); + + + holeHull = new SimpleHull(); + + holeHull.AddVertex(IMM); + holeHull.AddVertex(IMP); + holeHull.AddVertex(IPP); + holeHull.AddVertex(IPM); + } + if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + { + float hollowFactorF = (float)fhollowFactor / (float)50000; + + Vertex IQ1Q15 = new Vertex(-0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f); + Vertex IQ1Q16 = new Vertex(-0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f); + Vertex IQ1Q17 = new Vertex(-0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f); + Vertex IQ1Q18 = new Vertex(-0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f); + Vertex IQ1Q19 = new Vertex(-0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f); + + Vertex IQ2Q10 = new Vertex(+0.0f * hollowFactorF, -0.50f * hollowFactorF, 0.0f); + Vertex IQ2Q11 = new Vertex(+0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f); + Vertex IQ2Q12 = new Vertex(+0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f); + Vertex IQ2Q13 = new Vertex(+0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f); + Vertex IQ2Q14 = new Vertex(+0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f); + Vertex IQ2Q15 = new Vertex(+0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f); + Vertex IQ2Q16 = new Vertex(+0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f); + Vertex IQ2Q17 = new Vertex(+0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f); + Vertex IQ2Q18 = new Vertex(+0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f); + Vertex IQ2Q19 = new Vertex(+0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f); + + Vertex IQ2Q20 = new Vertex(+0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f); + Vertex IQ2Q21 = new Vertex(+0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f); + Vertex IQ2Q22 = new Vertex(+0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f); + Vertex IQ2Q23 = new Vertex(+0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f); + Vertex IQ2Q24 = new Vertex(+0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f); + Vertex IQ2Q25 = new Vertex(+0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f); + Vertex IQ2Q26 = new Vertex(+0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f); + Vertex IQ2Q27 = new Vertex(+0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f); + Vertex IQ2Q28 = new Vertex(+0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f); + Vertex IQ2Q29 = new Vertex(+0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f); + + Vertex IQ1Q20 = new Vertex(+0.0f * hollowFactorF, +0.50f * hollowFactorF, 0.0f); + Vertex IQ1Q21 = new Vertex(-0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f); + Vertex IQ1Q22 = new Vertex(-0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f); + Vertex IQ1Q23 = new Vertex(-0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f); + Vertex IQ1Q24 = new Vertex(-0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f); + Vertex IQ1Q25 = new Vertex(-0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f); + Vertex IQ1Q26 = new Vertex(-0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f); + Vertex IQ1Q27 = new Vertex(-0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f); + Vertex IQ1Q28 = new Vertex(-0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f); + Vertex IQ1Q29 = new Vertex(-0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f); + + Vertex IQ1Q10 = new Vertex(-0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f); + Vertex IQ1Q11 = new Vertex(-0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f); + Vertex IQ1Q12 = new Vertex(-0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f); + Vertex IQ1Q13 = new Vertex(-0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f); + Vertex IQ1Q14 = new Vertex(-0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f); + + //Counter clockwise around the quadrants + holeHull = new SimpleHull(); + holeHull.AddVertex(IQ1Q15); + holeHull.AddVertex(IQ1Q14); + holeHull.AddVertex(IQ1Q13); + holeHull.AddVertex(IQ1Q12); + holeHull.AddVertex(IQ1Q11); + holeHull.AddVertex(IQ1Q10); + + holeHull.AddVertex(IQ1Q29); + holeHull.AddVertex(IQ1Q28); + holeHull.AddVertex(IQ1Q27); + holeHull.AddVertex(IQ1Q26); + holeHull.AddVertex(IQ1Q25); + holeHull.AddVertex(IQ1Q24); + holeHull.AddVertex(IQ1Q23); + holeHull.AddVertex(IQ1Q22); + holeHull.AddVertex(IQ1Q21); + holeHull.AddVertex(IQ1Q20); + + holeHull.AddVertex(IQ2Q29); + holeHull.AddVertex(IQ2Q28); + holeHull.AddVertex(IQ2Q27); + holeHull.AddVertex(IQ2Q26); + holeHull.AddVertex(IQ2Q25); + holeHull.AddVertex(IQ2Q24); + holeHull.AddVertex(IQ2Q23); + holeHull.AddVertex(IQ2Q22); + holeHull.AddVertex(IQ2Q21); + holeHull.AddVertex(IQ2Q20); + + holeHull.AddVertex(IQ2Q19); + holeHull.AddVertex(IQ2Q18); + holeHull.AddVertex(IQ2Q17); + holeHull.AddVertex(IQ2Q16); + holeHull.AddVertex(IQ2Q15); + holeHull.AddVertex(IQ2Q14); + holeHull.AddVertex(IQ2Q13); + holeHull.AddVertex(IQ2Q12); + holeHull.AddVertex(IQ2Q11); + holeHull.AddVertex(IQ2Q10); + + holeHull.AddVertex(IQ1Q19); + holeHull.AddVertex(IQ1Q18); + holeHull.AddVertex(IQ1Q17); + holeHull.AddVertex(IQ1Q16); + } + if (hshape == HollowShape.Triangle) + { + float hollowFactorF = (float)fhollowFactor / (float)50000; + Vertex IMM = new Vertex(-0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f); + Vertex IPM = new Vertex(+0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f); + Vertex IPP = new Vertex(-0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f); + + + + holeHull = new SimpleHull(); + + holeHull.AddVertex(IMM); + holeHull.AddVertex(IPP); + holeHull.AddVertex(IPM); + + } + + return holeHull; + + + } + + private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + // Builds the z (+ and -) surfaces of a box shaped prim + { + UInt16 hollowFactor = primShape.ProfileHollow; + UInt16 profileBegin = primShape.ProfileBegin; + UInt16 profileEnd = primShape.ProfileEnd; + UInt16 taperX = primShape.PathScaleX; + UInt16 taperY = primShape.PathScaleY; + UInt16 pathShearX = primShape.PathShearX; + UInt16 pathShearY = primShape.PathShearY; + + + //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString()); + //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString()); + //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString()); + //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString()); + + // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface + // of a block are basically the same + // They may be warped differently but the shape is identical + // So we only create one surface as a model and derive both plus and minus surface of the block from it + // This is done in a model space where the block spans from -.5 to +.5 in X and Y + // The mapping to Scene space is done later during the "extrusion" phase + + // Base + Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f); + Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f); + Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f); + Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f); + + SimpleHull outerHull = new SimpleHull(); + outerHull.AddVertex(MM); + outerHull.AddVertex(PM); + outerHull.AddVertex(PP); + outerHull.AddVertex(MP); + + // Deal with cuts now + if ((profileBegin != 0) || (profileEnd != 0)) + { + double fProfileBeginAngle = profileBegin/50000.0*360.0; + // In degree, for easier debugging and understanding + fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y + double fProfileEndAngle = 360.0 - profileEnd/50000.0*360.0; // Pathend comes as complement to 1.0 + fProfileEndAngle -= (90.0 + 45.0); + if (fProfileBeginAngle < fProfileEndAngle) + fProfileEndAngle -= 360.0; + + // Note, that we don't want to cut out a triangle, even if this is a + // good approximation for small cuts. Indeed we want to cut out an arc + // and we approximate this arc by a polygon chain + // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space + // So it can easily be subtracted from the outer hull + int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5); + // how many steps do we need with approximately 45 degree + double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps; + + Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); + + // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull + SimpleHull cutHull = new SimpleHull(); + cutHull.AddVertex(origin); + for (int i = 0; i < iSteps; i++) + { + double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!! + Vertex v = Vertex.FromAngle(angle*Math.PI/180.0); + cutHull.AddVertex(v); + } + Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0); + // Calculated separately to avoid errors + cutHull.AddVertex(legEnd); + + //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); + SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); + + outerHull = cuttedHull; + } + + // Deal with the hole here + if (hollowFactor > 0) + { + + SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor); + if (holeHull != null) + { + SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); + + outerHull = hollowedHull; + } + } + + Mesh m = new Mesh(); + + Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); + Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); + Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); + + m.Add(Seed1); + m.Add(Seed2); + m.Add(Seed3); + + m.Add(new Triangle(Seed1, Seed2, Seed3)); + m.Add(outerHull.getVertices()); + + InsertVertices(m.vertices, 3, m.triangles); + m.DumpRaw(baseDir, primName, "Proto first Mesh"); + + m.Remove(Seed1); + m.Remove(Seed2); + m.Remove(Seed3); + m.DumpRaw(baseDir, primName, "Proto seeds removed"); + + m.RemoveTrianglesOutside(outerHull); + m.DumpRaw(baseDir, primName, "Proto outsides removed"); + + foreach (Triangle t in m.triangles) + { + PhysicsVector n = t.getNormal(); + if (n.Z < 0.0) + t.invertNormal(); + } + + Extruder extr = new Extruder(); + + extr.size = size; + + if (taperX != 100) + { + if (taperX > 100) + { + extr.taperTopFactorX = 1.0f - ((float)taperX / 200); + //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); + } + else + { + extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100); + //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); + } + + } + + if (taperY != 100) + { + if (taperY > 100) + { + extr.taperTopFactorY = 1.0f - ((float)taperY / 200); + //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); + } + else + { + extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); + //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); + } + } + + + if (pathShearX != 0) + { + if (pathShearX > 50) { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); + // m_log.Warn("pushX: " + extr.pushX); + } + else + { + extr.pushX = (float)pathShearX / 100; + // m_log.Warn("pushX: " + extr.pushX); + } + } + + if (pathShearY != 0) + { + if (pathShearY > 50) { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); + //m_log.Warn("pushY: " + extr.pushY); + } + else + { + extr.pushY = (float)pathShearY / 100; + //m_log.Warn("pushY: " + extr.pushY); + } + } + + Mesh result = extr.Extrude(m); + result.DumpRaw(baseDir, primName, "Z extruded"); + return result; + } + + private static Mesh CreateCyllinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + // Builds the z (+ and -) surfaces of a box shaped prim + { + UInt16 hollowFactor = primShape.ProfileHollow; + UInt16 profileBegin = primShape.ProfileBegin; + UInt16 profileEnd = primShape.ProfileEnd; + UInt16 taperX = primShape.PathScaleX; + UInt16 taperY = primShape.PathScaleY; + UInt16 pathShearX = primShape.PathShearX; + UInt16 pathShearY = primShape.PathShearY; + + // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface + // of a block are basically the same + // They may be warped differently but the shape is identical + // So we only create one surface as a model and derive both plus and minus surface of the block from it + // This is done in a model space where the block spans from -.5 to +.5 in X and Y + // The mapping to Scene space is done later during the "extrusion" phase + + // Base + // Q1Q15 = Quadrant 1, Quadrant1, Vertex 5 + Vertex Q1Q15 = new Vertex(-0.35f, -0.35f, 0.0f); + Vertex Q1Q16 = new Vertex(-0.30f, -0.40f, 0.0f); + Vertex Q1Q17 = new Vertex(-0.24f, -0.43f, 0.0f); + Vertex Q1Q18 = new Vertex(-0.18f, -0.46f, 0.0f); + Vertex Q1Q19 = new Vertex(-0.11f, -0.48f, 0.0f); + + Vertex Q2Q10 = new Vertex(+0.0f, -0.50f, 0.0f); + Vertex Q2Q11 = new Vertex(+0.11f, -0.48f, 0.0f); + Vertex Q2Q12 = new Vertex(+0.18f, -0.46f, 0.0f); + Vertex Q2Q13 = new Vertex(+0.24f, -0.43f, 0.0f); + Vertex Q2Q14 = new Vertex(+0.30f, -0.40f, 0.0f); + Vertex Q2Q15 = new Vertex(+0.35f, -0.35f, 0.0f); + Vertex Q2Q16 = new Vertex(+0.40f, -0.30f, 0.0f); + Vertex Q2Q17 = new Vertex(+0.43f, -0.24f, 0.0f); + Vertex Q2Q18 = new Vertex(+0.46f, -0.18f, 0.0f); + Vertex Q2Q19 = new Vertex(+0.48f, -0.11f, 0.0f); + + Vertex Q2Q20 = new Vertex(+0.50f, +0.0f, 0.0f); + Vertex Q2Q21 = new Vertex(+0.48f, +0.11f, 0.0f); + Vertex Q2Q22 = new Vertex(+0.46f, +0.18f, 0.0f); + Vertex Q2Q23 = new Vertex(+0.43f, +0.24f, 0.0f); + Vertex Q2Q24 = new Vertex(+0.40f, +0.30f, 0.0f); + Vertex Q2Q25 = new Vertex(+0.35f, +0.35f, 0.0f); + Vertex Q2Q26 = new Vertex(+0.30f, +0.40f, 0.0f); + Vertex Q2Q27 = new Vertex(+0.24f, +0.43f, 0.0f); + Vertex Q2Q28 = new Vertex(+0.18f, +0.46f, 0.0f); + Vertex Q2Q29 = new Vertex(+0.11f, +0.48f, 0.0f); + + Vertex Q1Q20 = new Vertex(+0.0f, +0.50f, 0.0f); + Vertex Q1Q21 = new Vertex(-0.11f, +0.48f, 0.0f); + Vertex Q1Q22 = new Vertex(-0.18f, +0.46f, 0.0f); + Vertex Q1Q23 = new Vertex(-0.24f, +0.43f, 0.0f); + Vertex Q1Q24 = new Vertex(-0.30f, +0.40f, 0.0f); + Vertex Q1Q25 = new Vertex(-0.35f, +0.35f, 0.0f); + Vertex Q1Q26 = new Vertex(-0.40f, +0.30f, 0.0f); + Vertex Q1Q27 = new Vertex(-0.43f, +0.24f, 0.0f); + Vertex Q1Q28 = new Vertex(-0.46f, +0.18f, 0.0f); + Vertex Q1Q29 = new Vertex(-0.48f, +0.11f, 0.0f); + + Vertex Q1Q10 = new Vertex(-0.50f, +0.0f, 0.0f); + Vertex Q1Q11 = new Vertex(-0.48f, -0.11f, 0.0f); + Vertex Q1Q12 = new Vertex(-0.46f, -0.18f, 0.0f); + Vertex Q1Q13 = new Vertex(-0.43f, -0.24f, 0.0f); + Vertex Q1Q14 = new Vertex(-0.40f, -0.30f, 0.0f); + + SimpleHull outerHull = new SimpleHull(); + //Clockwise around the quadrants + outerHull.AddVertex(Q1Q15); + outerHull.AddVertex(Q1Q16); + outerHull.AddVertex(Q1Q17); + outerHull.AddVertex(Q1Q18); + outerHull.AddVertex(Q1Q19); + + outerHull.AddVertex(Q2Q10); + outerHull.AddVertex(Q2Q11); + outerHull.AddVertex(Q2Q12); + outerHull.AddVertex(Q2Q13); + outerHull.AddVertex(Q2Q14); + outerHull.AddVertex(Q2Q15); + outerHull.AddVertex(Q2Q16); + outerHull.AddVertex(Q2Q17); + outerHull.AddVertex(Q2Q18); + outerHull.AddVertex(Q2Q19); + + outerHull.AddVertex(Q2Q20); + outerHull.AddVertex(Q2Q21); + outerHull.AddVertex(Q2Q22); + outerHull.AddVertex(Q2Q23); + outerHull.AddVertex(Q2Q24); + outerHull.AddVertex(Q2Q25); + outerHull.AddVertex(Q2Q26); + outerHull.AddVertex(Q2Q27); + outerHull.AddVertex(Q2Q28); + outerHull.AddVertex(Q2Q29); + + outerHull.AddVertex(Q1Q20); + outerHull.AddVertex(Q1Q21); + outerHull.AddVertex(Q1Q22); + outerHull.AddVertex(Q1Q23); + outerHull.AddVertex(Q1Q24); + outerHull.AddVertex(Q1Q25); + outerHull.AddVertex(Q1Q26); + outerHull.AddVertex(Q1Q27); + outerHull.AddVertex(Q1Q28); + outerHull.AddVertex(Q1Q29); + + outerHull.AddVertex(Q1Q10); + outerHull.AddVertex(Q1Q11); + outerHull.AddVertex(Q1Q12); + outerHull.AddVertex(Q1Q13); + outerHull.AddVertex(Q1Q14); + + // Deal with cuts now + if ((profileBegin != 0) || (profileEnd != 0)) + { + double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; + // In degree, for easier debugging and understanding + //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y + double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 + //fProfileEndAngle -= (90.0 + 45.0); + if (fProfileBeginAngle < fProfileEndAngle) + fProfileEndAngle -= 360.0; + + // Note, that we don't want to cut out a triangle, even if this is a + // good approximation for small cuts. Indeed we want to cut out an arc + // and we approximate this arc by a polygon chain + // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space + // So it can easily be subtracted from the outer hull + int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); + // how many steps do we need with approximately 45 degree + double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps; + + Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); + + // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull + SimpleHull cutHull = new SimpleHull(); + cutHull.AddVertex(origin); + for (int i = 0; i < iSteps; i++) + { + double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!! + Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); + cutHull.AddVertex(v); + } + Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); + // Calculated separately to avoid errors + cutHull.AddVertex(legEnd); + + // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); + SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); + + outerHull = cuttedHull; + } + + // Deal with the hole here + if (hollowFactor > 0) + { + SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor); + if (holeHull != null) + { + SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); + + outerHull = hollowedHull; + } + } + + Mesh m = new Mesh(); + + Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); + Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); + Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); + + m.Add(Seed1); + m.Add(Seed2); + m.Add(Seed3); + + m.Add(new Triangle(Seed1, Seed2, Seed3)); + m.Add(outerHull.getVertices()); + + InsertVertices(m.vertices, 3, m.triangles); + m.DumpRaw(baseDir, primName, "Proto first Mesh"); + + m.Remove(Seed1); + m.Remove(Seed2); + m.Remove(Seed3); + m.DumpRaw(baseDir, primName, "Proto seeds removed"); + + m.RemoveTrianglesOutside(outerHull); + m.DumpRaw(baseDir, primName, "Proto outsides removed"); + + foreach (Triangle t in m.triangles) + { + PhysicsVector n = t.getNormal(); + if (n.Z < 0.0) + t.invertNormal(); + } + + Extruder extr = new Extruder(); + + extr.size = size; + if (taperX != 100) + { + if (taperX > 100) + { + extr.taperTopFactorX = 1.0f - ((float)taperX / 200); + //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); + } + else + { + extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100); + //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); + } + + } + + if (taperY != 100) + { + if (taperY > 100) + { + extr.taperTopFactorY = 1.0f - ((float)taperY / 200); + //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); + } + else + { + extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); + //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); + } + } + + if (pathShearX != 0) + { + if (pathShearX > 50) + { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); + //m_log.Warn("pushX: " + extr.pushX); + } + else + { + extr.pushX = (float)pathShearX / 100; + //m_log.Warn("pushX: " + extr.pushX); + } + } + + if (pathShearY != 0) + { + if (pathShearY > 50) + { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); + //m_log.Warn("pushY: " + extr.pushY); + } + else + { + extr.pushY = (float)pathShearY / 100; + //m_log.Warn("pushY: " + extr.pushY); + } + } + + Mesh result = extr.Extrude(m); + result.DumpRaw(baseDir, primName, "Z extruded"); + return result; + } + + private static Mesh CreatePrismMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + // Builds the z (+ and -) surfaces of a box shaped prim + { + UInt16 hollowFactor = primShape.ProfileHollow; + UInt16 profileBegin = primShape.ProfileBegin; + UInt16 profileEnd = primShape.ProfileEnd; + UInt16 taperX = primShape.PathScaleX; + UInt16 taperY = primShape.PathScaleY; + UInt16 pathShearX = primShape.PathShearX; + UInt16 pathShearY = primShape.PathShearY; + + //m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString()); + //m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString()); + //m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString()); + //m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString()); + + // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface + // of a block are basically the same + // They may be warped differently but the shape is identical + // So we only create one surface as a model and derive both plus and minus surface of the block from it + // This is done in a model space where the block spans from -.5 to +.5 in X and Y + // The mapping to Scene space is done later during the "extrusion" phase + + // Base + Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); + Vertex PM = new Vertex(+0.5f, 0f, 0.0f); + Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); + + + SimpleHull outerHull = new SimpleHull(); + outerHull.AddVertex(MM); + outerHull.AddVertex(PM); + outerHull.AddVertex(PP); + + // Deal with cuts now + if ((profileBegin != 0) || (profileEnd != 0)) + { + double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; + // In degree, for easier debugging and understanding + //fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y + double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 + //fProfileEndAngle -= (90.0 + 45.0); + if (fProfileBeginAngle < fProfileEndAngle) + fProfileEndAngle -= 360.0; + + // Note, that we don't want to cut out a triangle, even if this is a + // good approximation for small cuts. Indeed we want to cut out an arc + // and we approximate this arc by a polygon chain + // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space + // So it can easily be subtracted from the outer hull + int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); + // how many steps do we need with approximately 45 degree + double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps; + + Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); + + // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull + SimpleHull cutHull = new SimpleHull(); + cutHull.AddVertex(origin); + for (int i = 0; i < iSteps; i++) + { + double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!! + Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); + cutHull.AddVertex(v); + } + Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); + // Calculated separately to avoid errors + cutHull.AddVertex(legEnd); + + //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); + SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); + + outerHull = cuttedHull; + } + + // Deal with the hole here + if (hollowFactor > 0) + { + SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor); + if (holeHull != null) + { + SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); + + outerHull = hollowedHull; + } + } + + Mesh m = new Mesh(); + + Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); + Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); + Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); + + m.Add(Seed1); + m.Add(Seed2); + m.Add(Seed3); + + m.Add(new Triangle(Seed1, Seed2, Seed3)); + m.Add(outerHull.getVertices()); + + InsertVertices(m.vertices, 3, m.triangles); + m.DumpRaw(baseDir, primName, "Proto first Mesh"); + + m.Remove(Seed1); + m.Remove(Seed2); + m.Remove(Seed3); + m.DumpRaw(baseDir, primName, "Proto seeds removed"); + + m.RemoveTrianglesOutside(outerHull); + m.DumpRaw(baseDir, primName, "Proto outsides removed"); + + foreach (Triangle t in m.triangles) + { + PhysicsVector n = t.getNormal(); + if (n.Z < 0.0) + t.invertNormal(); + } + + Extruder extr = new Extruder(); + + extr.size = size; + + if (taperX != 100) + { + if (taperX > 100) + { + extr.taperTopFactorX = 1.0f - ((float)taperX / 200); + //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); + } + else + { + extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100); + //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); + } + } + + if (taperY != 100) + { + if (taperY > 100) + { + extr.taperTopFactorY = 1.0f - ((float)taperY / 200); + //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); + } + else + { + extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); + //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); + } + } + + if (pathShearX != 0) + { + if (pathShearX > 50) + { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); + // m_log.Warn("pushX: " + extr.pushX); + } + else + { + extr.pushX = (float)pathShearX / 100; + // m_log.Warn("pushX: " + extr.pushX); + } + } + + if (pathShearY != 0) + { + if (pathShearY > 50) + { + // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 + extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); + //m_log.Warn("pushY: " + extr.pushY); + } + else + { + extr.pushY = (float)pathShearY / 100; + //m_log.Warn("pushY: " + extr.pushY); + } + } + + Mesh result = extr.Extrude(m); + result.DumpRaw(baseDir, primName, "Z extruded"); + return result; + } + + public static void CalcNormals(Mesh mesh) + { + int iTriangles = mesh.triangles.Count; + + mesh.normals = new float[iTriangles*3]; + + int i = 0; + foreach (Triangle t in mesh.triangles) + { + float ux, uy, uz; + float vx, vy, vz; + float wx, wy, wz; + + ux = t.v1.X; + uy = t.v1.Y; + uz = t.v1.Z; + + vx = t.v2.X; + vy = t.v2.Y; + vz = t.v2.Z; + + wx = t.v3.X; + wy = t.v3.Y; + wz = t.v3.Z; + + + // Vectors for edges + float e1x, e1y, e1z; + float e2x, e2y, e2z; + + e1x = ux - vx; + e1y = uy - vy; + e1z = uz - vz; + + e2x = ux - wx; + e2y = uy - wy; + e2z = uz - wz; + + + // Cross product for normal + float nx, ny, nz; + nx = e1y*e2z - e1z*e2y; + ny = e1z*e2x - e1x*e2z; + nz = e1x*e2y - e1y*e2x; + + // Length + float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz); + + // Normalized "normal" + nx /= l; + ny /= l; + nz /= l; + + mesh.normals[i] = nx; + mesh.normals[i + 1] = ny; + mesh.normals[i + 2] = nz; + + i += 3; + } + } + + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) + { + Mesh mesh = null; + + switch (primShape.ProfileShape) + { + case ProfileShape.Square: + mesh = CreateBoxMesh(primName, primShape, size); + CalcNormals(mesh); + break; + case ProfileShape.Circle: + if (primShape.PathCurve == (byte)Extrusion.Straight) + { + mesh = CreateCyllinderMesh(primName, primShape, size); + CalcNormals(mesh); + } + break; + case ProfileShape.EquilateralTriangle: + mesh = CreatePrismMesh(primName, primShape, size); + CalcNormals(mesh); + break; + + default: + mesh = CreateBoxMesh(primName, primShape, size); + CalcNormals(mesh); + //Set default mesh to cube otherwise it'll return + // null and crash on the 'setMesh' method in the physics plugins. + //mesh = null; + break; + } + + return mesh; + } + } +} diff --git a/OpenSim/Region/Physics/Meshing/SimpleHull.cs b/OpenSim/Region/Physics/Meshing/SimpleHull.cs index 1461376ef2..58b9a0e5a6 100644 --- a/OpenSim/Region/Physics/Meshing/SimpleHull.cs +++ b/OpenSim/Region/Physics/Meshing/SimpleHull.cs @@ -1,395 +1,395 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using OpenSim.Framework.Console; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.Meshing -{ - // A simple hull is a set of vertices building up to simplices that border a region - // The word simple referes to the fact, that this class assumes, that all simplices - // do not intersect - // Simple hulls can be added and subtracted. - // Vertices can be checked to lie inside a hull - // Also note, that the sequence of the vertices is important and defines if the region that - // is defined by the hull lies inside or outside the simplex chain - public class SimpleHull - { - private List vertices = new List(); - private List holeVertices = new List(); // Only used, when the hull is hollow - - // Adds a vertex to the end of the list - public void AddVertex(Vertex v) - { - vertices.Add(v); - } - - public override String ToString() - { - String result = ""; - foreach (Vertex v in vertices) - { - result += "b:" + v.ToString() + "\n"; - } - - return result; - } - - - public List getVertices() - { - List newVertices = new List(); - - newVertices.AddRange(vertices); - newVertices.Add(null); - newVertices.AddRange(holeVertices); - - return newVertices; - } - - public SimpleHull Clone() - { - SimpleHull result = new SimpleHull(); - foreach (Vertex v in vertices) - { - result.AddVertex(v.Clone()); - } - - foreach (Vertex v in holeVertices) - { - result.holeVertices.Add(v.Clone()); - } - - return result; - } - - public bool IsPointIn(Vertex v1) - { - int iCounter = 0; - List simplices = buildSimplexList(); - foreach (Simplex s in simplices) - { - // Send a ray along the positive X-Direction - // Note, that this direction must correlate with the "below" interpretation - // of handling for the special cases below - PhysicsVector intersection = s.RayIntersect(v1, new PhysicsVector(1.0f, 0.0f, 0.0f), true); - - if (intersection == null) - continue; // No intersection. Done. More tests to follow otherwise - - // Did we hit the end of a simplex? - // Then this can be one of two special cases: - // 1. we go through a border exactly at a joint - // 2. we have just marginally touched a corner - // 3. we can slide along a border - // Solution: If the other vertex is "below" the ray, we don't count it - // Thus corners pointing down are counted twice, corners pointing up are not counted - // borders are counted once - if (intersection.IsIdentical(s.v1, 0.001f)) - { - if (s.v2.Y < v1.Y) - continue; - } - // Do this for the other vertex two - if (intersection.IsIdentical(s.v2, 0.001f)) - { - if (s.v1.Y < v1.Y) - continue; - } - iCounter++; - } - - return iCounter%2 == 1; // Point is inside if the number of intersections is odd - } - - public bool containsPointsFrom(SimpleHull otherHull) - { - foreach (Vertex v in otherHull.vertices) - { - if (IsPointIn(v)) - return true; - } - - return false; - } - - - private List buildSimplexList() - { - List result = new List(); - - // Not asserted but assumed: at least three vertices - for (int i = 0; i < vertices.Count - 1; i++) - { - Simplex s = new Simplex(vertices[i], vertices[i + 1]); - result.Add(s); - } - Simplex s1 = new Simplex(vertices[vertices.Count - 1], vertices[0]); - result.Add(s1); - - if (holeVertices.Count == 0) - return result; - - // Same here. At least three vertices in hole assumed - for (int i = 0; i < holeVertices.Count - 1; i++) - { - Simplex s = new Simplex(holeVertices[i], holeVertices[i + 1]); - result.Add(s); - } - - s1 = new Simplex(holeVertices[holeVertices.Count - 1], holeVertices[0]); - result.Add(s1); - return result; - } - - private bool InsertVertex(Vertex v, int iAfter) - { - vertices.Insert(iAfter + 1, v); - return true; - } - - private Vertex getNextVertex(Vertex currentVertex) - { - int iCurrentIndex; - iCurrentIndex = vertices.IndexOf(currentVertex); - - // Error handling for iCurrentIndex==-1 should go here (and probably never will) - - iCurrentIndex++; - if (iCurrentIndex == vertices.Count) - iCurrentIndex = 0; - - return vertices[iCurrentIndex]; - } - - public Vertex FindVertex(Vertex vBase, float tolerance) - { - foreach (Vertex v in vertices) - { - if (v.IsIdentical(vBase, tolerance)) - return v; - } - - return null; - } - - public void FindIntersection(Simplex s, ref Vertex Intersection, ref Vertex nextVertex) - { - Vertex bestIntersection = null; - float distToV1 = Single.PositiveInfinity; - Simplex bestIntersectingSimplex = null; - - List simple = buildSimplexList(); - foreach (Simplex sTest in simple) - { - PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f); - - Vertex vTemp = null; - if (vvTemp != null) - vTemp = new Vertex(vvTemp); - - if (vTemp != null) - { - PhysicsVector diff = (s.v1 - vTemp); - float distTemp = diff.length(); - - if (bestIntersection == null || distTemp < distToV1) - { - bestIntersection = vTemp; - distToV1 = distTemp; - bestIntersectingSimplex = sTest; - } - } // end if vTemp - } // end foreach - - Intersection = bestIntersection; - if (bestIntersectingSimplex != null) - nextVertex = bestIntersectingSimplex.v2; - else - nextVertex = null; - } - - - public static SimpleHull SubtractHull(SimpleHull baseHull, SimpleHull otherHull) - { - SimpleHull baseHullClone = baseHull.Clone(); - SimpleHull otherHullClone = otherHull.Clone(); - bool intersects = false; - - MainLog.Instance.Debug("State before intersection detection"); - MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString()); - MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString()); - - { - int iBase, iOther; - - // Insert into baseHull - for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) - { - int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; - Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]); - - for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++) - { - int iOtherNext = (iOther + 1)%otherHullClone.vertices.Count; - Simplex sOther = - new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]); - - PhysicsVector intersect = Simplex.Intersect(sBase, sOther, 0.001f, -.001f, 0.999f, 1.001f); - if (intersect != null) - { - Vertex vIntersect = new Vertex(intersect); - baseHullClone.vertices.Insert(iBase + 1, vIntersect); - sBase.v2 = vIntersect; - intersects = true; - } - } - } - } - - MainLog.Instance.Debug("State after intersection detection for the base hull"); - MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString()); - - { - int iOther, iBase; - - // Insert into otherHull - for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++) - { - int iOtherNext = (iOther + 1)%otherHullClone.vertices.Count; - Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]); - - for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) - { - int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; - Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]); - - PhysicsVector intersect = Simplex.Intersect(sBase, sOther, -.001f, 0.001f, 1.001f, 0.999f); - if (intersect != null) - { - Vertex vIntersect = new Vertex(intersect); - otherHullClone.vertices.Insert(iOther + 1, vIntersect); - sOther.v2 = vIntersect; - intersects = true; - } - } - } - } - - MainLog.Instance.Debug("State after intersection detection for the base hull"); - MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString()); - - - bool otherIsInBase = baseHullClone.containsPointsFrom(otherHullClone); - if (!intersects && otherIsInBase) - { - // We have a hole here - baseHullClone.holeVertices = otherHullClone.vertices; - return baseHullClone; - } - - - SimpleHull result = new SimpleHull(); - - // Find a good starting Simplex from baseHull - // A good starting simplex is one that is outside otherHull - // Such a simplex must exist, otherwise the result will be empty - Vertex baseStartVertex = null; - { - int iBase; - for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) - { - int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; - Vertex center = new Vertex((baseHullClone.vertices[iBase] + baseHullClone.vertices[iBaseNext])/2.0f); - bool isOutside = !otherHullClone.IsPointIn(center); - if (isOutside) - { - baseStartVertex = baseHullClone.vertices[iBaseNext]; - break; - } - } - } - - - if (baseStartVertex == null) // i.e. no simplex fulfilled the "outside" condition. - // In otherwords, subtractHull completely embraces baseHull - { - return result; - } - - // The simplex that *starts* with baseStartVertex is outside the cutting hull, - // so we can start our walk with the next vertex without loosing a branch - Vertex V1 = baseStartVertex; - bool onBase = true; - - // And here is how we do the magic :-) - // Start on the base hull. - // Walk the vertices in the positive direction - // For each vertex check, whether it is a vertex shared with the other hull - // if this is the case, switch over to walking the other vertex list. - // Note: The other hull *must* go backwards to our starting point (via several orther vertices) - // Thus it is important that the cutting hull has the inverse directional sense than the - // base hull!!!!!!!!! (means if base goes CW around it's center cutting hull must go CCW) - - bool done = false; - while (!done) - { - result.AddVertex(V1); - Vertex nextVertex = null; - if (onBase) - { - nextVertex = otherHullClone.FindVertex(V1, 0.001f); - } - else - { - nextVertex = baseHullClone.FindVertex(V1, 0.001f); - } - - if (nextVertex != null) // A node that represents an intersection - { - V1 = nextVertex; // Needed to find the next vertex on the other hull - onBase = !onBase; - } - - if (onBase) - V1 = baseHullClone.getNextVertex(V1); - else - V1 = otherHullClone.getNextVertex(V1); - - if (V1 == baseStartVertex) - done = true; - } - - MainLog.Instance.Debug("The resulting Hull is:\n{1}", 0, result.ToString()); - - return result; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.Meshing +{ + // A simple hull is a set of vertices building up to simplices that border a region + // The word simple referes to the fact, that this class assumes, that all simplices + // do not intersect + // Simple hulls can be added and subtracted. + // Vertices can be checked to lie inside a hull + // Also note, that the sequence of the vertices is important and defines if the region that + // is defined by the hull lies inside or outside the simplex chain + public class SimpleHull + { + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private List vertices = new List(); + private List holeVertices = new List(); // Only used, when the hull is hollow + + // Adds a vertex to the end of the list + public void AddVertex(Vertex v) + { + vertices.Add(v); + } + + public override String ToString() + { + String result = String.Empty; + foreach (Vertex v in vertices) + { + result += "b:" + v.ToString() + "\n"; + } + + return result; + } + + + public List getVertices() + { + List newVertices = new List(); + + newVertices.AddRange(vertices); + newVertices.Add(null); + newVertices.AddRange(holeVertices); + + return newVertices; + } + + public SimpleHull Clone() + { + SimpleHull result = new SimpleHull(); + foreach (Vertex v in vertices) + { + result.AddVertex(v.Clone()); + } + + foreach (Vertex v in holeVertices) + { + result.holeVertices.Add(v.Clone()); + } + + return result; + } + + public bool IsPointIn(Vertex v1) + { + int iCounter = 0; + List simplices = buildSimplexList(); + foreach (Simplex s in simplices) + { + // Send a ray along the positive X-Direction + // Note, that this direction must correlate with the "below" interpretation + // of handling for the special cases below + PhysicsVector intersection = s.RayIntersect(v1, new PhysicsVector(1.0f, 0.0f, 0.0f), true); + + if (intersection == null) + continue; // No intersection. Done. More tests to follow otherwise + + // Did we hit the end of a simplex? + // Then this can be one of two special cases: + // 1. we go through a border exactly at a joint + // 2. we have just marginally touched a corner + // 3. we can slide along a border + // Solution: If the other vertex is "below" the ray, we don't count it + // Thus corners pointing down are counted twice, corners pointing up are not counted + // borders are counted once + if (intersection.IsIdentical(s.v1, 0.001f)) + { + if (s.v2.Y < v1.Y) + continue; + } + // Do this for the other vertex two + if (intersection.IsIdentical(s.v2, 0.001f)) + { + if (s.v1.Y < v1.Y) + continue; + } + iCounter++; + } + + return iCounter%2 == 1; // Point is inside if the number of intersections is odd + } + + public bool containsPointsFrom(SimpleHull otherHull) + { + foreach (Vertex v in otherHull.vertices) + { + if (IsPointIn(v)) + return true; + } + + return false; + } + + + private List buildSimplexList() + { + List result = new List(); + + // Not asserted but assumed: at least three vertices + for (int i = 0; i < vertices.Count - 1; i++) + { + Simplex s = new Simplex(vertices[i], vertices[i + 1]); + result.Add(s); + } + Simplex s1 = new Simplex(vertices[vertices.Count - 1], vertices[0]); + result.Add(s1); + + if (holeVertices.Count == 0) + return result; + + // Same here. At least three vertices in hole assumed + for (int i = 0; i < holeVertices.Count - 1; i++) + { + Simplex s = new Simplex(holeVertices[i], holeVertices[i + 1]); + result.Add(s); + } + + s1 = new Simplex(holeVertices[holeVertices.Count - 1], holeVertices[0]); + result.Add(s1); + return result; + } + + private bool InsertVertex(Vertex v, int iAfter) + { + vertices.Insert(iAfter + 1, v); + return true; + } + + private Vertex getNextVertex(Vertex currentVertex) + { + int iCurrentIndex; + iCurrentIndex = vertices.IndexOf(currentVertex); + + // Error handling for iCurrentIndex==-1 should go here (and probably never will) + + iCurrentIndex++; + if (iCurrentIndex == vertices.Count) + iCurrentIndex = 0; + + return vertices[iCurrentIndex]; + } + + public Vertex FindVertex(Vertex vBase, float tolerance) + { + foreach (Vertex v in vertices) + { + if (v.IsIdentical(vBase, tolerance)) + return v; + } + + return null; + } + + public void FindIntersection(Simplex s, ref Vertex Intersection, ref Vertex nextVertex) + { + Vertex bestIntersection = null; + float distToV1 = Single.PositiveInfinity; + Simplex bestIntersectingSimplex = null; + + List simple = buildSimplexList(); + foreach (Simplex sTest in simple) + { + PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f); + + Vertex vTemp = null; + if (vvTemp != null) + vTemp = new Vertex(vvTemp); + + if (vTemp != null) + { + PhysicsVector diff = (s.v1 - vTemp); + float distTemp = diff.length(); + + if (bestIntersection == null || distTemp < distToV1) + { + bestIntersection = vTemp; + distToV1 = distTemp; + bestIntersectingSimplex = sTest; + } + } + } + + Intersection = bestIntersection; + if (bestIntersectingSimplex != null) + nextVertex = bestIntersectingSimplex.v2; + else + nextVertex = null; + } + + + public static SimpleHull SubtractHull(SimpleHull baseHull, SimpleHull otherHull) + { + SimpleHull baseHullClone = baseHull.Clone(); + SimpleHull otherHullClone = otherHull.Clone(); + bool intersects = false; + + //m_log.Debug("State before intersection detection"); + //m_log.DebugFormat("The baseHull is:\n{1}", 0, baseHullClone.ToString()); + //m_log.DebugFormat("The otherHull is:\n{1}", 0, otherHullClone.ToString()); + + { + int iBase, iOther; + + // Insert into baseHull + for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) + { + int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; + Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]); + + for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++) + { + int iOtherNext = (iOther + 1)%otherHullClone.vertices.Count; + Simplex sOther = + new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]); + + PhysicsVector intersect = Simplex.Intersect(sBase, sOther, 0.001f, -.001f, 0.999f, 1.001f); + if (intersect != null) + { + Vertex vIntersect = new Vertex(intersect); + baseHullClone.vertices.Insert(iBase + 1, vIntersect); + sBase.v2 = vIntersect; + intersects = true; + } + } + } + } + + //m_log.Debug("State after intersection detection for the base hull"); + //m_log.DebugFormat("The baseHull is:\n{1}", 0, baseHullClone.ToString()); + + { + int iOther, iBase; + + // Insert into otherHull + for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++) + { + int iOtherNext = (iOther + 1)%otherHullClone.vertices.Count; + Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]); + + for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) + { + int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; + Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]); + + PhysicsVector intersect = Simplex.Intersect(sBase, sOther, -.001f, 0.001f, 1.001f, 0.999f); + if (intersect != null) + { + Vertex vIntersect = new Vertex(intersect); + otherHullClone.vertices.Insert(iOther + 1, vIntersect); + sOther.v2 = vIntersect; + intersects = true; + } + } + } + } + + //m_log.Debug("State after intersection detection for the base hull"); + //m_log.DebugFormat("The otherHull is:\n{1}", 0, otherHullClone.ToString()); + + bool otherIsInBase = baseHullClone.containsPointsFrom(otherHullClone); + if (!intersects && otherIsInBase) + { + // We have a hole here + baseHullClone.holeVertices = otherHullClone.vertices; + return baseHullClone; + } + + SimpleHull result = new SimpleHull(); + + // Find a good starting Simplex from baseHull + // A good starting simplex is one that is outside otherHull + // Such a simplex must exist, otherwise the result will be empty + Vertex baseStartVertex = null; + { + int iBase; + for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++) + { + int iBaseNext = (iBase + 1)%baseHullClone.vertices.Count; + Vertex center = new Vertex((baseHullClone.vertices[iBase] + baseHullClone.vertices[iBaseNext])/2.0f); + bool isOutside = !otherHullClone.IsPointIn(center); + if (isOutside) + { + baseStartVertex = baseHullClone.vertices[iBaseNext]; + break; + } + } + } + + + if (baseStartVertex == null) // i.e. no simplex fulfilled the "outside" condition. + // In otherwords, subtractHull completely embraces baseHull + { + return result; + } + + // The simplex that *starts* with baseStartVertex is outside the cutting hull, + // so we can start our walk with the next vertex without loosing a branch + Vertex V1 = baseStartVertex; + bool onBase = true; + + // And here is how we do the magic :-) + // Start on the base hull. + // Walk the vertices in the positive direction + // For each vertex check, whether it is a vertex shared with the other hull + // if this is the case, switch over to walking the other vertex list. + // Note: The other hull *must* go backwards to our starting point (via several orther vertices) + // Thus it is important that the cutting hull has the inverse directional sense than the + // base hull!!!!!!!!! (means if base goes CW around it's center cutting hull must go CCW) + + bool done = false; + while (!done) + { + result.AddVertex(V1); + Vertex nextVertex = null; + if (onBase) + { + nextVertex = otherHullClone.FindVertex(V1, 0.001f); + } + else + { + nextVertex = baseHullClone.FindVertex(V1, 0.001f); + } + + if (nextVertex != null) // A node that represents an intersection + { + V1 = nextVertex; // Needed to find the next vertex on the other hull + onBase = !onBase; + } + + if (onBase) + V1 = baseHullClone.getNextVertex(V1); + else + V1 = otherHullClone.getNextVertex(V1); + + if (V1 == baseStartVertex) + done = true; + } + + //m_log.DebugFormat("The resulting Hull is:\n{1}", 0, result.ToString()); + + return result; + } + } +} diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index 3ad226c86b..433f3c152f 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -1,609 +1,871 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using Axiom.Math; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using System.Runtime.InteropServices; // rex - -namespace OpenSim.Region.Physics.OdePlugin -{ - public class OdeCharacter : PhysicsActor - { - private PhysicsVector _position; - private d.Vector3 _zeroPosition; - private d.Matrix3 m_StandUpRotation; - private bool _zeroFlag = false; - private bool m_lastUpdateSent = false; - private PhysicsVector _velocity; - private PhysicsVector _target_velocity; - private PhysicsVector _acceleration; - private PhysicsVector m_rotationalVelocity; - private float m_density = 50f; - private bool m_pidControllerActive = true; - private static float PID_D = 3020.0f; - private static float PID_P = 7000.0f; - private static float POSTURE_SERVO = 10000.0f; - public static float CAPSULE_RADIUS = 0.5f; - public float CAPSULE_LENGTH = 0.79f; - private bool flying = false; - private bool m_iscolliding = false; - private bool m_iscollidingGround = false; - private bool m_wascolliding = false; - private bool m_wascollidingGround = false; - private bool m_iscollidingObj = false; - private bool m_wascollidingObj = false; - private bool m_alwaysRun = false; - private bool m_hackSentFall = false; - private bool m_hackSentFly = false; - private string m_name = ""; - - private bool[] m_colliderarr = new bool[11]; - private bool[] m_colliderGroundarr = new bool[11]; - - - private bool jumping = false; - //private float gravityAccel; - public IntPtr Body; - private GCHandle gchBody; // rex - - private OdeScene _parent_scene; - public IntPtr Shell; - private GCHandle gchShell; // rex - - public IntPtr Amotor; - public d.Mass ShellMass; - public bool collidelock = false; - - public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, uint localID) // rex, localID added - { - m_localID = localID; // rex - _velocity = new PhysicsVector(); - _target_velocity = new PhysicsVector(); - _position = pos; - _acceleration = new PhysicsVector(); - _parent_scene = parent_scene; - - m_StandUpRotation = - new d.Matrix3(0.8184158f, -0.5744568f, -0.0139677f, 0.5744615f, 0.8185215f, -0.004074608f, 0.01377355f, - -0.004689182f, 0.9998941f); - - for (int i = 0; i < 11; i++) - { - m_colliderarr[i] = false; - } - - lock (OdeScene.OdeLock) - { - int dAMotorEuler = 1; - Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); - gchShell = GCHandle.Alloc(Shell, GCHandleType.Pinned); // rex - - d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); - Body = d.BodyCreate(parent_scene.world); - gchBody = GCHandle.Alloc(Body, GCHandleType.Pinned); // rex - - d.BodySetMass(Body, ref ShellMass); - d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); - d.GeomSetBody(Shell, Body); - - - d.BodySetRotation(Body, ref m_StandUpRotation); - - - //Amotor = d.JointCreateAMotor(parent_scene.world, IntPtr.Zero); - //d.JointAttach(Amotor, Body, IntPtr.Zero); - //d.JointSetAMotorMode(Amotor, dAMotorEuler); - //d.JointSetAMotorNumAxes(Amotor, 3); - //d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0); - //d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0); - ///d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1); - //d.JointSetAMotorAngle(Amotor, 0, 0); - //d.JointSetAMotorAngle(Amotor, 1, 0); - //d.JointSetAMotorAngle(Amotor, 2, 0); - //d.JointSetAMotorParam(Amotor, 0, -0); - //d.JointSetAMotorParam(Amotor, 0x200, -0); - //d.JointSetAMotorParam(Amotor, 0x100, -0); - // d.JointSetAMotorParam(Amotor, 0, 0); - // d.JointSetAMotorParam(Amotor, 3, 0); - // d.JointSetAMotorParam(Amotor, 2, 0); - } - m_name = avName; - parent_scene.geom_name_map[Shell] = avName; - parent_scene.actor_name_map[Shell] = (PhysicsActor) this; - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override bool SetAlwaysRun - { - get { return m_alwaysRun; } - set { m_alwaysRun = value; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool Flying - { - get { return flying; } - set { flying = value; } - } - - public override bool IsColliding - { - get { return m_iscolliding; } - set - { - int i; - int truecount = 0; - int falsecount = 0; - - if (m_colliderarr.Length >= 10) - { - for (i = 0; i < 10; i++) - { - m_colliderarr[i] = m_colliderarr[i + 1]; - } - } - m_colliderarr[10] = value; - - for (i = 0; i < 11; i++) - { - if (m_colliderarr[i]) - { - truecount++; - } - else - { - falsecount++; - } - } - - // Equal truecounts and false counts means we're colliding with something. - - if (falsecount > 1.2*truecount) - { - m_iscolliding = false; - } - else - { - m_iscolliding = true; - } - if (m_wascolliding != m_iscolliding) - { - //base.SendCollisionUpdate(new CollisionEventUpdate()); - } - m_wascolliding = m_iscolliding; - } - } - - public override bool CollidingGround - { - get { return m_iscollidingGround; } - set - { - int i; - int truecount = 0; - int falsecount = 0; - - if (m_colliderGroundarr.Length >= 10) - { - for (i = 0; i < 10; i++) - { - m_colliderGroundarr[i] = m_colliderGroundarr[i + 1]; - } - } - m_colliderGroundarr[10] = value; - - for (i = 0; i < 11; i++) - { - if (m_colliderGroundarr[i]) - { - truecount++; - } - else - { - falsecount++; - } - } - - // Equal truecounts and false counts means we're colliding with something. - - if (falsecount > 1.2*truecount) - { - m_iscollidingGround = false; - } - else - { - m_iscollidingGround = true; - } - if (m_wascollidingGround != m_iscollidingGround) - { - //base.SendCollisionUpdate(new CollisionEventUpdate()); - } - m_wascollidingGround = m_iscollidingGround; - } - } - - public override bool CollidingObj - { - get { return m_iscollidingObj; } - set - { - m_iscollidingObj = value; - if (value) - m_pidControllerActive = false; - else - m_pidControllerActive = true; - } - } - - public void SetPidStatus(bool status) - { - m_pidControllerActive = status; - } - - public override PhysicsVector Position - { - get { return _position; } - set - { - lock (OdeScene.OdeLock) - { - d.BodySetPosition(Body, value.X, value.Y, value.Z); - _position = value; - } - } - } - - public override PhysicsVector RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override PhysicsVector Size - { - get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); } - set - { - m_pidControllerActive = true; - lock (OdeScene.OdeLock) - { - PhysicsVector SetSize = value; - float prevCapsule = CAPSULE_LENGTH; - float capsuleradius = CAPSULE_RADIUS; - capsuleradius = 0.2f; - - CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.43f))); // subtract 43% of the size - d.BodyDestroy(Body); - gchBody.Free(); // rex - d.GeomDestroy(Shell); - gchShell.Free(); // rex - //MainLog.Instance.Verbose("PHYSICS", "Set Avatar Height To: " + (CAPSULE_RADIUS + CAPSULE_LENGTH)); - Shell = d.CreateCapsule(_parent_scene.space, capsuleradius, CAPSULE_LENGTH); - gchShell = GCHandle.Alloc(Shell, GCHandleType.Pinned); // rex - d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); - Body = d.BodyCreate(_parent_scene.world); - gchBody = GCHandle.Alloc(Body, GCHandleType.Pinned); // rex - d.BodySetMass(Body, ref ShellMass); - d.BodySetPosition(Body, _position.X, _position.Y, - _position.Z + Math.Abs(CAPSULE_LENGTH - prevCapsule)); - d.GeomSetBody(Shell, Body); - } - _parent_scene.geom_name_map[Shell] = m_name; - _parent_scene.actor_name_map[Shell] = (PhysicsActor) this; - } - } - - public override float Mass - { - get - { - float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH); - return m_density*AVvolume; - } - } - - public override PhysicsVector Force - { - get { return new PhysicsVector(_target_velocity.X, _target_velocity.Y, _target_velocity.Z); } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override PhysicsVector Velocity - { - get { return _velocity; } - set - { - m_pidControllerActive = true; - _target_velocity = value; - } - } - - public override bool Kinematic - { - get { return false; } - set { } - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - public void SetAcceleration(PhysicsVector accel) - { - m_pidControllerActive = true; - _acceleration = accel; - } - - public override void AddForce(PhysicsVector force) - { - m_pidControllerActive = true; - _target_velocity.X += force.X; - _target_velocity.Y += force.Y; - _target_velocity.Z += force.Z; - - //m_lastUpdateSent = false; - } - - public void doForce(PhysicsVector force) - { - if (!collidelock) - { - d.BodyAddForce(Body, force.X, force.Y, force.Z); - - // ok -- let's stand up straight! - //d.Matrix3 StandUpRotationalMatrix = new d.Matrix3(0.8184158f, -0.5744568f, -0.0139677f, 0.5744615f, 0.8185215f, -0.004074608f, 0.01377355f, -0.004689182f, 0.9998941f); - //d.BodySetRotation(Body, ref StandUpRotationalMatrix); - //d.BodySetRotation(Body, ref m_StandUpRotation); - // The above matrix was generated with the amazing standup routine below by danX0r *cheer* - d.Vector3 feet; - d.Vector3 head; - d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet); - d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head); - float posture = head.Z - feet.Z; - - // restoring force proportional to lack of posture: - float servo = (2.5f - posture) * POSTURE_SERVO; - d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f); - d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f); - - //m_lastUpdateSent = false; - } - } - - public override void SetMomentum(PhysicsVector momentum) - { - } - - public void Move(float timeStep) - { - // no lock; for now it's only called from within Simulate() - if (m_pidControllerActive == false) - { - _zeroPosition = d.BodyGetPosition(Body); - } - //PidStatus = true; - - PhysicsVector vec = new PhysicsVector(); - d.Vector3 vel = d.BodyGetLinearVel(Body); - float movementdivisor = 1f; - - if (!m_alwaysRun) - { - movementdivisor = 1.3f; - } - else - { - movementdivisor = 0.8f; - } - - // if velocity is zero, use position control; otherwise, velocity control - if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding) - { - // keep track of where we stopped. No more slippin' & slidin' - if (!_zeroFlag) - { - _zeroFlag = true; - _zeroPosition = d.BodyGetPosition(Body); - } - if (m_pidControllerActive) - { - d.Vector3 pos = d.BodyGetPosition(Body); - vec.X = (_target_velocity.X - vel.X)*PID_D + (_zeroPosition.X - pos.X)*PID_P; - vec.Y = (_target_velocity.Y - vel.Y)*PID_D + (_zeroPosition.Y - pos.Y)*PID_P; - if (flying) - { - vec.Z = (_target_velocity.Z - vel.Z)*(PID_D + 5100) + (_zeroPosition.Z - pos.Z)*PID_P; - } - } - //PidStatus = true; - } - else - { - m_pidControllerActive = true; - _zeroFlag = false; - if (m_iscolliding || flying) - { - vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*PID_D; - vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*PID_D; - } - if (m_iscolliding && !flying && _target_velocity.Z > 0.0f) - { - d.Vector3 pos = d.BodyGetPosition(Body); - vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P; - if (_target_velocity.X > 0) - { - vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; - } - if (_target_velocity.Y > 0) - { - vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; - } - } - else if (!m_iscolliding && !flying) - { - d.Vector3 pos = d.BodyGetPosition(Body); - if (_target_velocity.X > 0) - { - vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; - } - if (_target_velocity.Y > 0) - { - vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; - } - } - - - if (flying) - { - vec.Z = (_target_velocity.Z - vel.Z)*(PID_D + 5100); - } - } - if (flying) - { - vec.Z += 10.0f; - } - - - doForce(vec); - } - - public void UpdatePositionAndVelocity() - { - // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! - d.Vector3 vec = d.BodyGetPosition(Body); - - // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) - if (vec.X < 0.0f) vec.X = 0.0f; - if (vec.Y < 0.0f) vec.Y = 0.0f; - if (vec.X > 255.95f) vec.X = 255.95f; - if (vec.Y > 255.95f) vec.Y = 255.95f; - - _position.X = vec.X; - _position.Y = vec.Y; - _position.Z = vec.Z; - - if (_zeroFlag) - { - _velocity.X = 0.0f; - _velocity.Y = 0.0f; - _velocity.Z = 0.0f; - if (!m_lastUpdateSent) - { - m_lastUpdateSent = true; - base.RequestPhysicsterseUpdate(); - //string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); - //int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); - //if (primScenAvatarIn == "0") - //{ - //MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in space with no prim. Arr:':" + arrayitem[0].ToString() + "," + arrayitem[1].ToString()); - //} - //else - //{ - // MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in Prim space':" + primScenAvatarIn + ". Arr:" + arrayitem[0].ToString() + "," + arrayitem[1].ToString()); - //} - } - } - else - { - m_lastUpdateSent = false; - vec = d.BodyGetLinearVel(Body); - _velocity.X = (vec.X); - _velocity.Y = (vec.Y); - - _velocity.Z = (vec.Z); - if (_velocity.Z < -6 && !m_hackSentFall) - { - m_hackSentFall = true; - //base.SendCollisionUpdate(new CollisionEventUpdate()); - m_pidControllerActive = false; - } - else if (flying && !m_hackSentFly) - { - //m_hackSentFly = true; - //base.SendCollisionUpdate(new CollisionEventUpdate()); - } - else - { - m_hackSentFly = false; - m_hackSentFall = false; - } - } - } - - public void Destroy() - { - lock (OdeScene.OdeLock) - { - // d.JointDestroy(Amotor); - d.GeomDestroy(Shell); - _parent_scene.geom_name_map.Remove(Shell); - d.BodyDestroy(Body); - } - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using Axiom.Math; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using System.Runtime.InteropServices; // rex + +namespace OpenSim.Region.Physics.OdePlugin +{ + /// + /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves. + /// + + public enum dParam : int + { + LowStop = 0, + HiStop = 1, + Vel = 2, + FMax = 3, + FudgeFactor = 4, + Bounce = 5, + CFM = 6, + ERP = 7, + StopCFM = 8, + LoStop2 = 256, + HiStop2 = 257, + LoStop3 = 512, + HiStop3 = 513 + } + public class OdeCharacter : PhysicsActor + { + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private PhysicsVector _position; + private d.Vector3 _zeroPosition; + private d.Matrix3 m_StandUpRotation; + private bool _zeroFlag = false; + private bool m_lastUpdateSent = false; + private PhysicsVector _velocity; + private PhysicsVector _target_velocity; + private PhysicsVector _acceleration; + private PhysicsVector m_rotationalVelocity; + private float m_mass = 80f; + private float m_density = 60f; + private bool m_pidControllerActive = true; + private float PID_D = 800.0f; + private float PID_P = 900.0f; + private static float POSTURE_SERVO = 10000.0f; + public static float CAPSULE_RADIUS = 0.37f; + public float CAPSULE_LENGTH = 2.140599f; + private float m_tensor = 3800000f; + private bool flying = false; + private bool m_iscolliding = false; + private bool m_iscollidingGround = false; + private bool m_wascolliding = false; + private bool m_wascollidingGround = false; + private bool m_iscollidingObj = false; + private bool m_wascollidingObj = false; + private bool m_alwaysRun = false; + private bool m_hackSentFall = false; + private bool m_hackSentFly = false; + private bool m_foundDebian = false; + private CollisionLocker ode; + + private string m_name = String.Empty; + + private bool[] m_colliderarr = new bool[11]; + private bool[] m_colliderGroundarr = new bool[11]; + + + private bool jumping = false; + //private float gravityAccel; + public IntPtr Body; + private GCHandle gchBody; // rex + + private OdeScene _parent_scene; + public IntPtr Shell; + private GCHandle gchShell; // rex + + public IntPtr Amotor; + public d.Mass ShellMass; + public bool collidelock = false; + + public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, CollisionLocker dode, PhysicsVector size) + { + ode = dode; + _velocity = new PhysicsVector(); + _target_velocity = new PhysicsVector(); + _position = pos; + _acceleration = new PhysicsVector(); + _parent_scene = parent_scene; + + if (System.Environment.OSVersion.Platform == PlatformID.Unix) + { + m_foundDebian = true; + m_tensor = 2000000f; + } + else + { + m_tensor = 1300000f; + } + + m_StandUpRotation = + new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f, + 0.5f); + + for (int i = 0; i < 11; i++) + { + m_colliderarr[i] = false; + } + CAPSULE_LENGTH = (size.Z - ((size.Z * 0.52f))); + + lock (OdeScene.OdeLock) + { + AvatarGeomAndBodyCreation(pos.X, pos.Y, pos.Z, m_tensor); + int dAMotorEuler = 1; + Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); + gchShell = GCHandle.Alloc(Shell, GCHandleType.Pinned); // rex + + d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); + Body = d.BodyCreate(parent_scene.world); + gchBody = GCHandle.Alloc(Body, GCHandleType.Pinned); // rex + + d.BodySetMass(Body, ref ShellMass); + d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); + d.GeomSetBody(Shell, Body); + + + d.BodySetRotation(Body, ref m_StandUpRotation); + + + //Amotor = d.JointCreateAMotor(parent_scene.world, IntPtr.Zero); + //d.JointAttach(Amotor, Body, IntPtr.Zero); + //d.JointSetAMotorMode(Amotor, dAMotorEuler); + //d.JointSetAMotorNumAxes(Amotor, 3); + //d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0); + //d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0); + ///d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1); + //d.JointSetAMotorAngle(Amotor, 0, 0); + //d.JointSetAMotorAngle(Amotor, 1, 0); + //d.JointSetAMotorAngle(Amotor, 2, 0); + //d.JointSetAMotorParam(Amotor, 0, -0); + //d.JointSetAMotorParam(Amotor, 0x200, -0); + //d.JointSetAMotorParam(Amotor, 0x100, -0); + // d.JointSetAMotorParam(Amotor, 0, 0); + // d.JointSetAMotorParam(Amotor, 3, 0); + // d.JointSetAMotorParam(Amotor, 2, 0); + } + m_name = avName; + parent_scene.geom_name_map[Shell] = avName; + parent_scene.actor_name_map[Shell] = (PhysicsActor) this; + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + /// + /// If this is set, the avatar will move faster + /// + public override bool SetAlwaysRun + { + get { return m_alwaysRun; } + set { m_alwaysRun = value; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + /// + /// Returns if the avatar is colliding in general. + /// This includes the ground and objects and avatar. + /// + public override bool IsColliding + { + get { return m_iscolliding; } + set + { + int i; + int truecount = 0; + int falsecount = 0; + + if (m_colliderarr.Length >= 10) + { + for (i = 0; i < 10; i++) + { + m_colliderarr[i] = m_colliderarr[i + 1]; + } + } + m_colliderarr[10] = value; + + for (i = 0; i < 11; i++) + { + if (m_colliderarr[i]) + { + truecount++; + } + else + { + falsecount++; + } + } + + // Equal truecounts and false counts means we're colliding with something. + + if (falsecount > 1.2*truecount) + { + m_iscolliding = false; + } + else + { + m_iscolliding = true; + } + if (m_wascolliding != m_iscolliding) + { + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + m_wascolliding = m_iscolliding; + } + } + + /// + /// Returns if an avatar is colliding with the ground + /// + public override bool CollidingGround + { + get { return m_iscollidingGround; } + set + { + // Collisions against the ground are not really reliable + // So, to get a consistant value we have to average the current result over time + // Currently we use 1 second = 10 calls to this. + int i; + int truecount = 0; + int falsecount = 0; + + if (m_colliderGroundarr.Length >= 10) + { + for (i = 0; i < 10; i++) + { + m_colliderGroundarr[i] = m_colliderGroundarr[i + 1]; + } + } + m_colliderGroundarr[10] = value; + + for (i = 0; i < 11; i++) + { + if (m_colliderGroundarr[i]) + { + truecount++; + } + else + { + falsecount++; + } + } + + // Equal truecounts and false counts means we're colliding with something. + + if (falsecount > 1.2*truecount) + { + m_iscollidingGround = false; + } + else + { + m_iscollidingGround = true; + } + if (m_wascollidingGround != m_iscollidingGround) + { + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + m_wascollidingGround = m_iscollidingGround; + } + } + + /// + /// Returns if the avatar is colliding with an object + /// + public override bool CollidingObj + { + get { return m_iscollidingObj; } + set + { + m_iscollidingObj = value; + if (value) + m_pidControllerActive = false; + else + m_pidControllerActive = true; + } + } + + /// + /// turn the PID controller on or off. + /// The PID Controller will turn on all by itself in many situations + /// + /// + public void SetPidStatus(bool status) + { + m_pidControllerActive = status; + } + + public override bool Stopped + { + get { return _zeroFlag; } + } + + /// + /// This 'puts' an avatar somewhere in the physics space. + /// Not really a good choice unless you 'know' it's a good + /// spot otherwise you're likely to orbit the avatar. + /// + public override PhysicsVector Position + { + get { return _position; } + set + { + lock (OdeScene.OdeLock) + { + d.BodySetPosition(Body, value.X, value.Y, value.Z); + _position = value; + } + } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + /// + /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight + /// and use it to offset landings properly + /// + public override PhysicsVector Size + { + get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); } + set + { + m_pidControllerActive = true; + lock (OdeScene.OdeLock) + { + d.JointDestroy(Amotor); + + PhysicsVector SetSize = value; + float prevCapsule = CAPSULE_LENGTH; + float capsuleradius = CAPSULE_RADIUS; + //capsuleradius = 0.2f; + + CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.52f))); // subtract 43% of the size + //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); + d.BodyDestroy(Body); + gchBody.Free(); // rex + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + + d.GeomDestroy(Shell); + AvatarGeomAndBodyCreation(_position.X, _position.Y, + _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); + Velocity = new PhysicsVector(0f, 0f, 0f); + + gchShell.Free(); // rex + //MainLog.Instance.Verbose("PHYSICS", "Set Avatar Height To: " + (CAPSULE_RADIUS + CAPSULE_LENGTH)); + Shell = d.CreateCapsule(_parent_scene.space, capsuleradius, CAPSULE_LENGTH); + gchShell = GCHandle.Alloc(Shell, GCHandleType.Pinned); // rex + d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); + Body = d.BodyCreate(_parent_scene.world); + gchBody = GCHandle.Alloc(Body, GCHandleType.Pinned); // rex + d.BodySetMass(Body, ref ShellMass); + d.BodySetPosition(Body, _position.X, _position.Y, + _position.Z + Math.Abs(CAPSULE_LENGTH - prevCapsule)); + d.GeomSetBody(Shell, Body); + } + _parent_scene.geom_name_map[Shell] = m_name; + _parent_scene.actor_name_map[Shell] = (PhysicsActor) this; + } + } + /// + /// This creates the Avatar's physical Surrogate at the position supplied + /// + /// + /// + /// + private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor) + { + + if (System.Environment.OSVersion.Platform == PlatformID.Unix) + { + m_foundDebian = true; + m_tensor = 2000000f; + } + else + { + m_tensor = 550000f; + } + + int dAMotorEuler = 1; + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); + d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH); + Body = d.BodyCreate(_parent_scene.world); + d.BodySetPosition(Body, npositionX, npositionY, npositionZ); + + d.BodySetMass(Body, ref ShellMass); + d.Matrix3 m_caprot; + // 90 Stand up on the cap of the capped cyllinder + d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2)); + + + d.GeomSetRotation(Shell, ref m_caprot); + d.BodySetRotation(Body, ref m_caprot); + + d.GeomSetBody(Shell, Body); + + + // The purpose of the AMotor here is to keep the avatar's physical + // surrogate from rotating while moving + Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); + d.JointAttach(Amotor, Body, IntPtr.Zero); + d.JointSetAMotorMode(Amotor, dAMotorEuler); + d.JointSetAMotorNumAxes(Amotor, 3); + d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0); + d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0); + d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1); + d.JointSetAMotorAngle(Amotor, 0, 0); + d.JointSetAMotorAngle(Amotor, 1, 0); + d.JointSetAMotorAngle(Amotor, 2, 0); + + // These lowstops and high stops are effectively (no wiggle room) + d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f); + + // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the + // capped cyllinder will fall over + d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor); + + //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); + //d.QfromR( + //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068, + // + //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); + //standupStraight(); + + + + } + + // + /// + /// Uses the capped cyllinder volume formula to calculate the avatar's mass. + /// This may be used in calculations in the scene/scenepresence + /// + public override float Mass + { + get + { + float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH); + return m_density*AVvolume; + } + } + + private void standupStraight() + { + + // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air. + // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you + // change appearance and when you enter the simulator + // After this routine is done, the amotor stabilizes much quicker + d.Vector3 feet; + d.Vector3 head; + d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet); + d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head); + float posture = head.Z - feet.Z; + + // restoring force proportional to lack of posture: + float servo = (2.5f - posture) * POSTURE_SERVO; + d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f); + d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f); + //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); + //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); + } + + public override PhysicsVector Force + { + get { return new PhysicsVector(_target_velocity.X, _target_velocity.Y, _target_velocity.Z); } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { + // There's a problem with PhysicsVector.Zero! Don't Use it Here! + if (_zeroFlag) + return new PhysicsVector(0f, 0f, 0f); + m_lastUpdateSent = false; + return _velocity; + } + set + { + m_pidControllerActive = true; + _target_velocity = value; + } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { + //Matrix3 or = Orientation.ToRotationMatrix(); + //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22); + //d.BodySetRotation(Body, ref ord); + + } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public void SetAcceleration(PhysicsVector accel) + { + m_pidControllerActive = true; + _acceleration = accel; + } + + /// + /// Adds the force supplied to the Target Velocity + /// The PID controller takes this target velocity and tries to make it a reality + /// + /// + public override void AddForce(PhysicsVector force) + { + m_pidControllerActive = true; + _target_velocity.X += force.X; + _target_velocity.Y += force.Y; + _target_velocity.Z += force.Z; + + //m_lastUpdateSent = false; + } + + /// + /// After all of the forces add up with 'add force' we apply them with doForce + /// + /// + public void doForce(PhysicsVector force) + { + if (!collidelock) + { + d.BodyAddForce(Body, force.X, force.Y, force.Z); + //d.BodySetRotation(Body, ref m_StandUpRotation); + //standupStraight(); + + } + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + + /// + /// Called from Simulate + /// This is the avatar's movement control + PID Controller + /// + /// + public void Move(float timeStep) + { + // no lock; for now it's only called from within Simulate() + + // If the PID Controller isn't active then we set our force + // calculating base velocity to the current position + if (System.Environment.OSVersion.Platform == PlatformID.Unix) + { + PID_D = 3200.0f; + PID_P = 1400.0f; + } + else + { + PID_D = 2200.0f; + PID_P = 900.0f; + } + + + if (m_pidControllerActive == false) + { + _zeroPosition = d.BodyGetPosition(Body); + } + //PidStatus = true; + + PhysicsVector vec = new PhysicsVector(); + d.Vector3 vel = d.BodyGetLinearVel(Body); + float movementdivisor = 1f; + + if (!m_alwaysRun) + { + movementdivisor = 1.3f; + } + else + { + movementdivisor = 0.8f; + } + + // if velocity is zero, use position control; otherwise, velocity control + if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding) + { + // keep track of where we stopped. No more slippin' & slidin' + if (!_zeroFlag) + { + _zeroFlag = true; + _zeroPosition = d.BodyGetPosition(Body); + } + if (m_pidControllerActive) + { + // We only want to deactivate the PID Controller if we think we want to have our surrogate + // react to the physics scene by moving it's position. + // Avatar to Avatar collisions + // Prim to avatar collisions + + d.Vector3 pos = d.BodyGetPosition(Body); + vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); + vec.Y = (_target_velocity.Y - vel.Y)*(PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2); + if (flying) + { + vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; + } + } + //PidStatus = true; + } + else + { + m_pidControllerActive = true; + _zeroFlag = false; + if (m_iscolliding && !flying) + { + // We're flying and colliding with something + vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D); + vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D); + } + else if (m_iscolliding && flying) + { + // We're flying and colliding with something + vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16); + vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16); + } + else if (!m_iscolliding && flying) + { + // We're flying and colliding with something + vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6); + vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6); + } + + if (m_iscolliding && !flying && _target_velocity.Z > 0.0f) + { + // We're colliding with something and we're not flying but we're moving + // This means we're walking or running. + d.Vector3 pos = d.BodyGetPosition(Body); + vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P; + if (_target_velocity.X > 0) + { + vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; + } + if (_target_velocity.Y > 0) + { + vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; + } + } + else if (!m_iscolliding && !flying) + { + // we're not colliding and we're not flying so that means we're falling! + // m_iscolliding includes collisions with the ground. + d.Vector3 pos = d.BodyGetPosition(Body); + if (_target_velocity.X > 0) + { + vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; + } + if (_target_velocity.Y > 0) + { + vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; + } + } + + + if (flying) + { + vec.Z = (_target_velocity.Z - vel.Z) * (PID_D); + } + } + if (flying) + { + vec.Z += (9.8f*m_mass); + } + + + doForce(vec); + } + + /// + /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. + /// + public void UpdatePositionAndVelocity() + { + // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! + d.Vector3 vec = d.BodyGetPosition(Body); + + // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) + if (vec.X < 0.0f) vec.X = 0.0f; + if (vec.Y < 0.0f) vec.Y = 0.0f; + if (vec.X > 255.95f) vec.X = 255.95f; + if (vec.Y > 255.95f) vec.Y = 255.95f; + + _position.X = vec.X; + _position.Y = vec.Y; + _position.Z = vec.Z; + + // Did we move last? = zeroflag + // This helps keep us from sliding all over + + if (_zeroFlag) + { + _velocity.X = 0.0f; + _velocity.Y = 0.0f; + _velocity.Z = 0.0f; + + // Did we send out the 'stopped' message? + if (!m_lastUpdateSent) + { + m_lastUpdateSent = true; + //base.RequestPhysicsterseUpdate(); + + } + } + else + { + m_lastUpdateSent = false; + vec = d.BodyGetLinearVel(Body); + _velocity.X = (vec.X); + _velocity.Y = (vec.Y); + + _velocity.Z = (vec.Z); + if (_velocity.Z < -6 && !m_hackSentFall) + { + // Collisionupdates will be used in the future, right now the're not being used. + m_hackSentFall = true; + //base.SendCollisionUpdate(new CollisionEventUpdate()); + m_pidControllerActive = false; + } + else if (flying && !m_hackSentFly) + { + //m_hackSentFly = true; + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + else + { + m_hackSentFly = false; + m_hackSentFall = false; + } + } + } + + /// + /// Cleanup the things we use in the scene. + /// + public void Destroy() + { + lock (OdeScene.OdeLock) + { + // Kill the Amotor + d.JointDestroy(Amotor); + + //kill the Geometry + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + + d.GeomDestroy(Shell); + _parent_scene.geom_name_map.Remove(Shell); + + //kill the body + d.BodyDestroy(Body); + } + } + public override void CrossingFailure() + { + + } + } +} diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 35021ec6da..012e7d94dd 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -1,1167 +1,1790 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using Axiom.Math; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -using System.Collections.Generic; // rex -using System.Runtime.InteropServices; // rex -using RexDotMeshLoader; // rex -using OpenSim.Framework.Console; // rex -using libsecondlife; // rex - -namespace OpenSim.Region.Physics.OdePlugin -{ - - // rex, new class - public class OdeCollisionMesh : IMesh - { - public float[] vertexListOrig; - public int[] indexListOrig; - - public float[] vertexList; - public int[] indexList; - public GCHandle gchVertexList; - public GCHandle gchIndexList; - - public LLVector3 BoundsMin = new LLVector3(); - public LLVector3 BoundsMax = new LLVector3(); - public bool m_BoundsScaling; - - public OdeCollisionMesh(int vVertexCount, int vIndexCount) - { - vertexList = new float[vVertexCount]; - gchVertexList = GCHandle.Alloc(vertexList, GCHandleType.Pinned); - vertexListOrig = new float[vVertexCount]; - - indexList = new int[vIndexCount]; - gchIndexList = GCHandle.Alloc(indexList, GCHandleType.Pinned); - indexListOrig = new int[vIndexCount]; - } - - public void FreeLists() - { - gchVertexList.Free(); - gchIndexList.Free(); - } - - public List getVertexList() - { - return null; - } - public int[] getIndexListAsInt() - { - return indexList; - } - public int[] getIndexListAsIntLocked() - { - return indexList; - } - public float[] getVertexListAsFloatLocked() - { - return vertexList; - } - } - - - public class OdePrim : PhysicsActor - { - public PhysicsVector _position; - private PhysicsVector _velocity; - private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f); - private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f); - private PhysicsVector m_rotationalVelocity; - private PhysicsVector _size; - private PhysicsVector _acceleration; - private Quaternion _orientation; - private PhysicsVector m_taintposition; - private PhysicsVector m_taintsize; - private Quaternion m_taintrot; - private bool m_taintshape = false; - private bool m_taintPhysics = false; - public bool m_taintremove = false; - - private IMesh _mesh; - private PrimitiveBaseShape _pbs; - private OdeScene _parent_scene; - public IntPtr m_targetSpace = (IntPtr) 0; - public IntPtr prim_geom; - public IntPtr _triMeshData; - private bool iscolliding = false; - private bool m_isphysical = false; - private bool m_throttleUpdates = false; - private int throttleCounter = 0; - public bool outofBounds = false; - private float m_density = 10.000006836f; // Aluminum g/cm3; - - - public bool _zeroFlag = false; - private bool m_lastUpdateSent = false; - - public IntPtr Body = (IntPtr) 0; - private String m_primName; - private PhysicsVector _target_velocity; - public d.Mass pMass; - - private int debugcounter = 0; - private bool m_DotMeshCollision = false; // rex - public bool m_BoundsScalingUpdate = false; // rex - private bool m_PrimVolume = false; // rex - - public OdePrim(String primName, OdeScene parent_scene, IntPtr targetSpace, PhysicsVector pos, PhysicsVector size, - Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, uint localID) - { - m_localID = localID; // rex - _velocity = new PhysicsVector(); - _position = pos; - m_taintposition = pos; - if (_position.X > 257) - { - _position.X = 257; - } - if (_position.X < 0) - { - _position.X = 0; - } - if (_position.Y > 257) - { - _position.Y = 257; - } - if (_position.Y < 0) - { - _position.Y = 0; - } - - _size = size; - m_taintsize = _size; - _acceleration = new PhysicsVector(); - m_rotationalVelocity = PhysicsVector.Zero; - _orientation = rotation; - m_taintrot = _orientation; - _mesh = mesh; - _pbs = pbs; - - _parent_scene = parent_scene; - m_targetSpace = targetSpace; - - if (pos.Z < 0) - m_isphysical = false; - else - { - m_isphysical = pisPhysical; - // If we're physical, we need to be in the master space for now. - // linksets *should* be in a space together.. but are not currently - if (m_isphysical) - m_targetSpace = _parent_scene.space; - } - m_primName = primName; - - lock (OdeScene.OdeLock) - { - if (mesh != null) - { - setMesh(parent_scene, mesh); - } - else - { - prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); - } - - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.W = rotation.w; - myrot.X = rotation.x; - myrot.Y = rotation.y; - myrot.Z = rotation.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - - - if (m_isphysical && Body == (IntPtr) 0) - { - enableBody(); - } - parent_scene.geom_name_map[prim_geom] = primName; - parent_scene.actor_name_map[prim_geom] = (PhysicsActor) this; - // don't do .add() here; old geoms get recycled with the same hash - } - } - - // rex, modified function, m_PrimVolume added - public override int PhysicsActorType - { - get - { - if (m_PrimVolume) - return (int)ActorTypes.PrimVolume; - else - return (int)ActorTypes.Prim; - } - set - { - if (value == (int)ActorTypes.PrimVolume) - m_PrimVolume = true; - else - m_PrimVolume = false; - } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public void enableBody() - { - // Sets the geom to a body - Body = d.BodyCreate(_parent_scene.world); - - setMass(); - d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.W = _orientation.w; - myrot.X = _orientation.x; - myrot.Y = _orientation.y; - myrot.Z = _orientation.z; - d.BodySetQuaternion(Body, ref myrot); - d.GeomSetBody(prim_geom, Body); - d.BodySetAutoDisableFlag(Body, true); - d.BodySetAutoDisableSteps(Body, 20); - - _parent_scene.addActivePrim(this); - } - - private float CalculateMass() - { - float volume = 0; - - // No material is passed to the physics engines yet.. soo.. - // we're using the m_density constant in the class definition - - - float returnMass = 0; - - switch (_pbs.ProfileShape) - { - case ProfileShape.Square: - // Profile Volume - - volume = _size.X*_size.Y*_size.Z; - - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage - - if (((float) _pbs.ProfileHollow/50000f) > 0.0) - { - float hollowAmount = (float) _pbs.ProfileHollow/50000f; - - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - // Cube Hollow volume calculation - float hollowsizex = _size.X*hollowAmount; - float hollowsizey = _size.Y*hollowAmount; - float hollowsizez = _size.Z*hollowAmount; - hollowVolume = hollowsizex*hollowsizey*hollowsizez; - break; - - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X/2; - float hLength = _size.Z; - - // pi * r2 * h - hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); - break; - - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y - - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); - break; - - default: - hollowVolume = 0; - break; - } - volume = volume - hollowVolume; - } - - break; - - default: - // we don't have all of the volume formulas yet so - // use the common volume formula for all - volume = _size.X*_size.Y*_size.Z; - break; - } - - // Calculate Path cut effect on volume - // Not exact, in the triangle hollow example - // They should never be zero or less then zero.. - // we'll ignore it if it's less then zero - - // ProfileEnd and ProfileBegin are values - // from 0 to 50000 - - // Turning them back into percentages so that I can cut that percentage off the volume - - float PathCutEndAmount = _pbs.ProfileEnd; - float PathCutStartAmount = _pbs.ProfileBegin; - if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) - { - float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); - - // Check the return amount for sanity - if (pathCutAmount >= 0.99f) - pathCutAmount = 0.99f; - - volume = volume - (volume*pathCutAmount); - } - - // Mass = density * volume - - returnMass = m_density*volume; - - return returnMass; - } - - public void setMass() - { - if (Body != (IntPtr) 0) - { - d.MassSetBoxTotal(out pMass, CalculateMass(), _size.X, _size.Y, _size.Z); - d.BodySetMass(Body, ref pMass); - } - } - - - public void disableBody() - { - //this kills the body so things like 'mesh' can re-create it. - if (Body != (IntPtr) 0) - { - _parent_scene.remActivePrim(this); - d.BodyDestroy(Body); - Body = (IntPtr) 0; - } - } - - public void setMesh(OdeScene parent_scene, IMesh mesh) - { - //Kill Body so that mesh can re-make the geom - if (IsPhysical && Body != (IntPtr) 0) - { - disableBody(); - } - float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory - int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage - int VertexCount = vertexList.GetLength(0)/3; - int IndexCount = indexList.GetLength(0); - - // rex, del old trimeshdata - if (_triMeshData != (IntPtr)0) - d.GeomTriMeshDataDestroy(_triMeshData); - _mesh = mesh; // rex, end - - _triMeshData = d.GeomTriMeshDataCreate(); - - d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount, - 3*sizeof (int)); - d.GeomTriMeshDataPreprocess(_triMeshData); - - prim_geom = d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null); - - if (IsPhysical && Body == (IntPtr) 0) - { - // Recreate the body - enableBody(); - } - } - - public void ProcessTaints(float timestep) - { - if (m_taintposition != _position) - Move(timestep); - - if (m_taintrot != _orientation) - rotate(timestep); - // - - if (m_taintPhysics != m_isphysical) - changePhysicsStatus(timestep); - // - - if (m_taintsize != _size) - changesize(timestep); - - if (m_BoundsScalingUpdate) // rex - changesize(timestep); - // - - if (m_taintshape) - changeshape(timestep); - // - } - - public void Move(float timestep) - { - if (m_isphysical) - { - // This is a fallback.. May no longer be necessary. - if (Body == (IntPtr) 0) - enableBody(); - //Prim auto disable after 20 frames, - ///if you move it, re-enable the prim manually. - d.BodyEnable(Body); - d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); - } - else - { - string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); - int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); - m_targetSpace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.SpaceAdd(m_targetSpace, prim_geom); - } - - m_taintposition = _position; - } - - // rex, function changed - public void rotate(float timestep) - { - d.Quaternion myrot = new d.Quaternion(); - - if (m_DotMeshCollision && _mesh != null) // rex, setting rot for collision 3d model - { - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - - Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0)); - Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0)); - Quaternion mytemprot = _orientation * meshRotA * meshRotB; - - myrot.W = mytemprot.w; - myrot.X = mytemprot.x; - myrot.Y = mytemprot.y; - myrot.Z = mytemprot.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - } - else - { - myrot.W = _orientation.w; - myrot.X = _orientation.x; - myrot.Y = _orientation.y; - myrot.Z = _orientation.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - } - - if (m_isphysical && Body != (IntPtr) 0) - { - d.BodySetQuaternion(Body, ref myrot); - } - - m_taintrot = _orientation; - } - - public void changePhysicsStatus(float timestap) - { - if (m_isphysical == true) - { - if (Body == (IntPtr) 0) - { - enableBody(); - } - } - else - { - if (Body != (IntPtr) 0) - { - disableBody(); - } - } - - - m_taintPhysics = m_isphysical; - } - - // rex, function changed - public void changesize(float timestamp) - { - string oldname = _parent_scene.geom_name_map[prim_geom]; - - // Cleanup of old prim geometry - if (_mesh != null) - { - // Cleanup meshing here - } - //kill body to rebuild - if (IsPhysical && Body != (IntPtr) 0) - { - disableBody(); - } - if (d.SpaceQuery(m_targetSpace, prim_geom)) - { - d.SpaceRemove(m_targetSpace, prim_geom); - } - d.GeomDestroy(prim_geom); - - // we don't need to do space calculation because the client sends a position update also. - - if (m_DotMeshCollision && _mesh != null) // rex, scaling dotmesh models - { - float[] scalefactor = new float[3]; - int vertindex = 0; - OdeCollisionMesh mesh = _mesh as OdeCollisionMesh; - - LLVector3 scalingvector = new LLVector3(_size.X, _size.Y, _size.Z); - if (mesh.m_BoundsScaling) - { - LLVector3 boundssize = mesh.BoundsMax - mesh.BoundsMin; - if (boundssize.X != 0) - scalingvector.X /= boundssize.X; - if (boundssize.Y != 0) - scalingvector.Z /= boundssize.Y; - if (boundssize.Z != 0) - scalingvector.Y /= boundssize.Z; - } - scalefactor[0] = scalingvector.X; - scalefactor[1] = scalingvector.Z; - scalefactor[2] = scalingvector.Y; - - for (int i = 0; i < mesh.vertexList.GetLength(0); i++) - { - mesh.vertexList[i] = mesh.vertexListOrig[i] * scalefactor[vertindex]; - vertindex++; - if (vertindex > 2) - vertindex = 0; - } - - for (int i = 0; i < mesh.indexList.GetLength(0); i++) - mesh.indexList[i] = mesh.indexListOrig[i]; - - setMesh(_parent_scene, mesh); - - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - - Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0)); - Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0)); - Quaternion mytemprot = _orientation * meshRotA * meshRotB; - - d.Quaternion myrot = new d.Quaternion(); - myrot.W = mytemprot.w; - myrot.X = mytemprot.x; - myrot.Y = mytemprot.y; - myrot.Z = mytemprot.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - - if (IsPhysical && Body == (IntPtr)0) - { - // Re creates body on size. - // EnableBody also does setMass() - enableBody(); - d.BodyEnable(Body); - } - } // rex, end scaling - // Construction of new prim - else if (_parent_scene.needsMeshing(_pbs)) - { - // Don't need to re-enable body.. it's done in SetMesh - IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); - // createmesh returns null when it's a shape that isn't a cube. - if (mesh != null) - { - setMesh(_parent_scene, mesh); - } - else - { - prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.W = _orientation.w; - myrot.X = _orientation.x; - myrot.Y = _orientation.y; - myrot.Z = _orientation.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - } - } - else - { - prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.W = _orientation.w; - myrot.X = _orientation.x; - myrot.Y = _orientation.y; - myrot.Z = _orientation.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - - - //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); - if (IsPhysical && Body == (IntPtr) 0) - { - // Re creates body on size. - // EnableBody also does setMass() - enableBody(); - d.BodyEnable(Body); - } - } - - _parent_scene.geom_name_map[prim_geom] = oldname; - - m_taintsize = _size; - m_BoundsScalingUpdate = false; // rex - } - - public void changeshape(float timestamp) - { - string oldname = _parent_scene.geom_name_map[prim_geom]; - - // Cleanup of old prim geometry and Bodies - if (IsPhysical && Body != (IntPtr) 0) - { - disableBody(); - } - d.GeomDestroy(prim_geom); - if (_mesh != null) - { - d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); - } - - // Construction of new prim - if (_parent_scene.needsMeshing(_pbs)) - { - IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); - if (mesh != null) - { - setMesh(_parent_scene, mesh); - } - else - { - prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); - } - } - else - { - prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); - } - if (IsPhysical && Body == (IntPtr) 0) - { - //re-create new body - enableBody(); - } - else - { - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.W = _orientation.w; - myrot.X = _orientation.x; - myrot.Y = _orientation.y; - myrot.Z = _orientation.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - } - _parent_scene.geom_name_map[prim_geom] = oldname; - - m_taintshape = false; - } - - public override bool IsPhysical - { - get { return m_isphysical; } - set { m_isphysical = value; } - } - - public void setPrimForRemoval() - { - m_taintremove = true; - } - - public override bool Flying - { - get { return false; //no flying prims for you - } - set { } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return m_throttleUpdates; } - set { m_throttleUpdates = value; } - } - - public override PhysicsVector Position - { - get { return _position; } - - set { _position = value; } - } - - public override PhysicsVector Size - { - get { return _size; } - set { _size = value; } - } - - public override float Mass - { - get { return CalculateMass(); } - } - - public override PhysicsVector Force - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { _pbs = value; } - } - - public override PhysicsVector Velocity - { - get - { - // Averate previous velocity with the new one so - // client object interpolation works a 'little' better - PhysicsVector returnVelocity = new PhysicsVector(); - returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; - returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; - returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; - return returnVelocity; - } - set { _velocity = value; } - } - - public override bool Kinematic - { - get { return false; } - set { } - } - - public override Quaternion Orientation - { - get { return _orientation; } - set { _orientation = value; } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - - public void SetAcceleration(PhysicsVector accel) - { - _acceleration = accel; - } - - public override void AddForce(PhysicsVector force) - { - } - - public override PhysicsVector RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public void UpdatePositionAndVelocity() - { - // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! - - if (Body != (IntPtr) 0) - { - d.Vector3 vec = d.BodyGetPosition(Body); - d.Quaternion ori = d.BodyGetQuaternion(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); - d.Vector3 rotvel = d.BodyGetAngularVel(Body); - - PhysicsVector l_position = new PhysicsVector(); - // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) - if (vec.X < 0.0f) vec.X = 0.0f; - if (vec.Y < 0.0f) vec.Y = 0.0f; - if (vec.X > 255.95f) vec.X = 255.95f; - if (vec.Y > 255.95f) vec.Y = 255.95f; - m_lastposition = _position; - - l_position.X = vec.X; - l_position.Y = vec.Y; - l_position.Z = vec.Z; - if (l_position.Z < 0) - { - // This is so prim that get lost underground don't fall forever and suck up - // - // Sim resources and memory. - // Disables the prim's movement physics.... - // It's a hack and will generate a console message if it fails. - - - //IsPhysical = false; - base.RaiseOutOfBounds(_position); - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - base.RequestPhysicsterseUpdate(); - m_throttleUpdates = false; - throttleCounter = 0; - _zeroFlag = true; - //outofBounds = true; - } - - if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) - && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) - && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)) - { - _zeroFlag = true; - } - else - { - //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString()); - _zeroFlag = false; - } - - - if (_zeroFlag) - { - // Supposedly this is supposed to tell SceneObjectGroup that - // no more updates need to be sent.. - // but it seems broken. - _velocity.X = 0.0f; - _velocity.Y = 0.0f; - _velocity.Z = 0.0f; - //_orientation.w = 0f; - //_orientation.x = 0f; - //_orientation.y = 0f; - //_orientation.z = 0f; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - if (!m_lastUpdateSent) - { - m_throttleUpdates = false; - throttleCounter = 0; - base.RequestPhysicsterseUpdate(); - m_lastUpdateSent = true; - } - } - else - { - m_lastVelocity = _velocity; - - _position = l_position; - - _velocity.X = vel.X; - _velocity.Y = vel.Y; - _velocity.Z = vel.Z; - - m_rotationalVelocity.X = rotvel.X; - m_rotationalVelocity.Y = rotvel.Y; - m_rotationalVelocity.Z = rotvel.Z; - //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString()); - _orientation.w = ori.W; - _orientation.x = ori.X; - _orientation.y = ori.Y; - _orientation.z = ori.Z; - m_lastUpdateSent = false; - if (!m_throttleUpdates || throttleCounter > 15) - { - base.RequestPhysicsterseUpdate(); - } - else - { - throttleCounter++; - } - } - m_lastposition = l_position; - } - else - { - // Not a body.. so Make sure the client isn't interpolating - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - _zeroFlag = true; - } - } - - public override void SetMomentum(PhysicsVector momentum) - { - } - - - // rex, new function. - // This function should be called only outside of simulation loop -> OdeLock used. - public override void SetCollisionMesh(byte[] vData, string MeshName, bool vbScaleMesh) - { - float[] tempVertexList; - float[] tempBounds; - int[] tempIndexList; - string errorMessage; - float[] scalefactor = new float[3]; - int vertindex = 0; - - lock (OdeScene.OdeLock) - { - // 1. Get rid of old mesh - m_DotMeshCollision = false; - if (_mesh != null) - { - if ((OdeCollisionMesh)_mesh != null) - (_mesh as OdeCollisionMesh).FreeLists(); - - _mesh = null; - } - - // 2. Try to load new colmesh - OdeCollisionMesh mesh = null; - if (vData != null) - { - DotMeshLoader.ReadDotMeshModel(vData, out tempVertexList, out tempIndexList, out tempBounds, out errorMessage); - - if (tempVertexList != null && tempIndexList != null) - { - mesh = new OdeCollisionMesh(tempVertexList.GetLength(0), tempIndexList.GetLength(0)); - mesh.m_BoundsScaling = vbScaleMesh; - mesh.BoundsMin.X = tempBounds[0]; - mesh.BoundsMin.Y = tempBounds[1]; - mesh.BoundsMin.Z = tempBounds[2]; - mesh.BoundsMax.X = tempBounds[3]; - mesh.BoundsMax.Y = tempBounds[4]; - mesh.BoundsMax.Z = tempBounds[5]; - - LLVector3 scalingvector = new LLVector3(_size.X, _size.Y, _size.Z); - if (vbScaleMesh) - { - LLVector3 boundssize = mesh.BoundsMax - mesh.BoundsMin; - if (boundssize.X != 0) - scalingvector.X /= boundssize.X; - if (boundssize.Y != 0) - scalingvector.Z /= boundssize.Y; - if (boundssize.Z != 0) - scalingvector.Y /= boundssize.Z; - } - - scalefactor[0] = scalingvector.X; - scalefactor[1] = scalingvector.Z; - scalefactor[2] = scalingvector.Y; - for (int i = 0; i < tempVertexList.GetLength(0); i++) - { - mesh.vertexListOrig[i] = tempVertexList[i]; - mesh.vertexList[i] = tempVertexList[i] * scalefactor[vertindex]; - - vertindex++; - if (vertindex > 2) - vertindex = 0; - } - - for (int i = 0; i < tempIndexList.GetLength(0); i++) - { - mesh.indexListOrig[i] = tempIndexList[i]; - mesh.indexList[i] = tempIndexList[i]; - } - - - } - else - MainLog.Instance.Error("PHYSICS", "Error importing mesh:" + MeshName + ", " + errorMessage); - } - - // 3. If mesh is null, must create the default collisionbox - if (mesh == null) - { - CreateDefaultCollision(); - return; - } - - // 4. If mesh loaded, use it - string oldname = _parent_scene.geom_name_map[prim_geom]; - m_DotMeshCollision = true; - - if (IsPhysical && Body != (IntPtr)0) - disableBody(); - - if (prim_geom != (IntPtr)0) - { - if (d.SpaceQuery(m_targetSpace, prim_geom)) - { - d.SpaceRemove(m_targetSpace, prim_geom); - } - d.GeomDestroy(prim_geom); - } - - setMesh(_parent_scene, mesh); - - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - - Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0)); - Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0)); - Quaternion mytemprot = _orientation * meshRotA * meshRotB; - - d.Quaternion myrot = new d.Quaternion(); - myrot.W = mytemprot.w; - myrot.X = mytemprot.x; - myrot.Y = mytemprot.y; - myrot.Z = mytemprot.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - - _parent_scene.geom_name_map[prim_geom] = oldname; - } - } - - - - - - // rex, function added - private void CreateDefaultCollision() - { - string oldname = _parent_scene.geom_name_map[prim_geom]; - - // Cleanup of old prim geometry - if (_mesh != null) - { - // Cleanup meshing here - } - //kill body to rebuild - if (IsPhysical && Body != (IntPtr)0) - { - disableBody(); - } - if (d.SpaceQuery(m_targetSpace, prim_geom)) - { - d.SpaceRemove(m_targetSpace, prim_geom); - } - d.GeomDestroy(prim_geom); - - // we don't need to do space calculation because the client sends a position update also. - // Construction of new prim - if (_parent_scene.needsMeshing(_pbs)) - { - // Don't need to re-enable body.. it's done in SetMesh - IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); - // createmesh returns null when it's a shape that isn't a cube. - if (mesh != null) - { - setMesh(_parent_scene, mesh); - } - else - { - prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.W = _orientation.w; - myrot.X = _orientation.x; - myrot.Y = _orientation.y; - myrot.Z = _orientation.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - } - } - else - { - prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.W = _orientation.w; - myrot.X = _orientation.x; - myrot.Y = _orientation.y; - myrot.Z = _orientation.z; - d.GeomSetQuaternion(prim_geom, ref myrot); - - - //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); - if (IsPhysical && Body == (IntPtr)0) - { - // Re creates body on size. - // EnableBody also does setMass() - enableBody(); - d.BodyEnable(Body); - } - } - _parent_scene.geom_name_map[prim_geom] = oldname; - } - - // rex, new function - public override void SetBoundsScaling(bool vbScaleMesh) - { - if (m_DotMeshCollision && _mesh != null) - { - (_mesh as OdeCollisionMesh).m_BoundsScaling = vbScaleMesh; - m_BoundsScalingUpdate = true; - } - } - - - - - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Axiom.Math; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +using System.Collections.Generic; // rex +using System.Runtime.InteropServices; // rex +using RexDotMeshLoader; // rex +using OpenSim.Framework.Console; // rex +using libsecondlife; // rex + +namespace OpenSim.Region.Physics.OdePlugin +{ + + // rex, new class + public class OdeCollisionMesh : IMesh + { + public float[] vertexListOrig; + public int[] indexListOrig; + + public float[] vertexList; + public int[] indexList; + public GCHandle gchVertexList; + public GCHandle gchIndexList; + + public LLVector3 BoundsMin = new LLVector3(); + public LLVector3 BoundsMax = new LLVector3(); + public bool m_BoundsScaling; + + public OdeCollisionMesh(int vVertexCount, int vIndexCount) + { + vertexList = new float[vVertexCount]; + gchVertexList = GCHandle.Alloc(vertexList, GCHandleType.Pinned); + vertexListOrig = new float[vVertexCount]; + + indexList = new int[vIndexCount]; + gchIndexList = GCHandle.Alloc(indexList, GCHandleType.Pinned); + indexListOrig = new int[vIndexCount]; + } + + public void FreeLists() + { + gchVertexList.Free(); + gchIndexList.Free(); + } + + public List getVertexList() + { + return null; + } + public int[] getIndexListAsInt() + { + return indexList; + } + public int[] getIndexListAsIntLocked() + { + return indexList; + } + public float[] getVertexListAsFloatLocked() + { + return vertexList; + } + } + + + public class OdePrim : PhysicsActor + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public PhysicsVector _position; + private PhysicsVector _velocity; + private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f); + private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f); + private PhysicsVector m_rotationalVelocity; + private PhysicsVector _size; + private PhysicsVector _acceleration; + private Quaternion _orientation; + private PhysicsVector m_taintposition; + private PhysicsVector m_taintsize; + private PhysicsVector m_taintVelocity = PhysicsVector.Zero; + private Quaternion m_taintrot; + private bool m_taintshape = false; + private bool m_taintPhysics = false; + public bool m_taintremove = false; + public bool m_taintdisable = false; + public bool m_disabled = false; + public bool m_taintadd = false; + public GCHandle gc; + private CollisionLocker ode; + + private bool m_taintforce = false; + private List m_forcelist = new List(); + + private IMesh _mesh; + private PrimitiveBaseShape _pbs; + private OdeScene _parent_scene; + public IntPtr m_targetSpace = (IntPtr) 0; + public IntPtr prim_geom; + public IntPtr prev_geom; + public IntPtr _triMeshData; + + private bool iscolliding = false; + private bool m_isphysical = false; + private bool m_throttleUpdates = false; + private int throttleCounter = 0; + public int m_interpenetrationcount = 0; + public int m_collisionscore = 0; + public int m_roundsUnderMotionThreshold = 0; + private int m_crossingfailures = 0; + + public bool outofBounds = false; + private float m_density = 10.000006836f; // Aluminum g/cm3; + + + public bool _zeroFlag = false; + private bool m_lastUpdateSent = false; + + public IntPtr Body = (IntPtr) 0; + private String m_primName; + private PhysicsVector _target_velocity; + public d.Mass pMass; + + private int debugcounter = 0; + private bool m_DotMeshCollision = false; // rex + public bool m_BoundsScalingUpdate = false; // rex + private bool m_PrimVolume = false; // rex + + public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, + Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) + { + m_localID = localID; // rex + + + gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned); + ode = dode; + _velocity = new PhysicsVector(); + _position = pos; + m_taintposition = pos; + if (_position.X > 257) + { + _position.X = 257; + } + if (_position.X < 0) + { + _position.X = 0; + } + if (_position.Y > 257) + { + _position.Y = 257; + } + if (_position.Y < 0) + { + _position.Y = 0; + } + + prim_geom = (IntPtr)0; + prev_geom = (IntPtr)0; + + _size = size; + m_taintsize = _size; + _acceleration = new PhysicsVector(); + m_rotationalVelocity = PhysicsVector.Zero; + _orientation = rotation; + m_taintrot = _orientation; + _mesh = mesh; + _pbs = pbs; + + _parent_scene = parent_scene; + m_targetSpace = (IntPtr)0; + + if (pos.Z < 0) + m_isphysical = false; + else + { + m_isphysical = pisPhysical; + // If we're physical, we need to be in the master space for now. + // linksets *should* be in a space together.. but are not currently + if (m_isphysical) + m_targetSpace = _parent_scene.space; + } + m_primName = primName; + m_taintadd = true; + _parent_scene.AddPhysicsActorTaint(this); + // don't do .add() here; old geoms get recycled with the same hash + + } + + /// + /// Nasty, however without this you get + /// 'invalid operation for locked space' when things are really loaded down + /// + /// + + public override int PhysicsActorType + { + get + { + if (m_PrimVolume) + return (int)ActorTypes.PrimVolume; + else + return (int)ActorTypes.Prim; + } + set + { + if (value == (int)ActorTypes.PrimVolume) + m_PrimVolume = true; + else + m_PrimVolume = false; + } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public void SetGeom(IntPtr geom) + { + prev_geom = prim_geom; + prim_geom = geom; + //m_log.Warn("Setting Geom to: " + prim_geom); + + } + + public void enableBody() + { + // Sets the geom to a body + Body = d.BodyCreate(_parent_scene.world); + + setMass(); + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.BodySetQuaternion(Body, ref myrot); + d.GeomSetBody(prim_geom, Body); + d.BodySetAutoDisableFlag(Body, true); + d.BodySetAutoDisableSteps(Body, 20); + + m_interpenetrationcount = 0; + m_collisionscore = 0; + m_disabled = false; + + _parent_scene.addActivePrim(this); + } + + private float CalculateMass() + { + float volume = 0; + + // No material is passed to the physics engines yet.. soo.. + // we're using the m_density constant in the class definition + + + float returnMass = 0; + + switch (_pbs.ProfileShape) + { + case ProfileShape.Square: + // Profile Volume + + volume = _size.X*_size.Y*_size.Z; + + // If the user has 'hollowed out' + // ProfileHollow is one of those 0 to 50000 values :P + // we like percentages better.. so turning into a percentage + + if (((float) _pbs.ProfileHollow/50000f) > 0.0) + { + float hollowAmount = (float) _pbs.ProfileHollow/50000f; + + // calculate the hollow volume by it's shape compared to the prim shape + float hollowVolume = 0; + switch (_pbs.HollowShape) + { + case HollowShape.Square: + case HollowShape.Same: + // Cube Hollow volume calculation + float hollowsizex = _size.X*hollowAmount; + float hollowsizey = _size.Y*hollowAmount; + float hollowsizez = _size.Z*hollowAmount; + hollowVolume = hollowsizex*hollowsizey*hollowsizez; + break; + + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation + float hRadius = _size.X/2; + float hLength = _size.Z; + + // pi * r2 * h + hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); + break; + + case HollowShape.Triangle: + // Equilateral Triangular Prism volume hollow calculation + // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + + float aLength = _size.Y; + // 1/2 abh + hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); + break; + + default: + hollowVolume = 0; + break; + } + volume = volume - hollowVolume; + } + + break; + + default: + // we don't have all of the volume formulas yet so + // use the common volume formula for all + volume = _size.X*_size.Y*_size.Z; + break; + } + + // Calculate Path cut effect on volume + // Not exact, in the triangle hollow example + // They should never be zero or less then zero.. + // we'll ignore it if it's less then zero + + // ProfileEnd and ProfileBegin are values + // from 0 to 50000 + + // Turning them back into percentages so that I can cut that percentage off the volume + + float PathCutEndAmount = _pbs.ProfileEnd; + float PathCutStartAmount = _pbs.ProfileBegin; + if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) + { + float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); + + // Check the return amount for sanity + if (pathCutAmount >= 0.99f) + pathCutAmount = 0.99f; + + volume = volume - (volume*pathCutAmount); + } + + // Mass = density * volume + + returnMass = m_density*volume; + + return returnMass; + } + + public void setMass() + { + if (Body != (IntPtr) 0) + { + d.MassSetBoxTotal(out pMass, CalculateMass(), _size.X, _size.Y, _size.Z); + d.BodySetMass(Body, ref pMass); + } + } + + + public void disableBody() + { + //this kills the body so things like 'mesh' can re-create it. + if (Body != (IntPtr) 0) + { + _parent_scene.remActivePrim(this); + d.BodyDestroy(Body); + Body = (IntPtr) 0; + } + m_disabled = true; + m_collisionscore = 0; + } + + public void setMesh(OdeScene parent_scene, IMesh mesh) + { + // This sleeper is there to moderate how long it takes between + // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object + + System.Threading.Thread.Sleep(10); + + //Kill Body so that mesh can re-make the geom + if (IsPhysical && Body != (IntPtr) 0) + { + disableBody(); + } + + float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory + int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage + int VertexCount = vertexList.GetLength(0)/3; + int IndexCount = indexList.GetLength(0); + + // rex, del old trimeshdata + if (_triMeshData != (IntPtr)0) + d.GeomTriMeshDataDestroy(_triMeshData); + _mesh = mesh; // rex, end + + _triMeshData = d.GeomTriMeshDataCreate(); + + d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount, + 3*sizeof (int)); + d.GeomTriMeshDataPreprocess(_triMeshData); + + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + + try + { + if (prim_geom == (IntPtr)0) + { + SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); + } + } + catch (System.AccessViolationException) + { + + m_log.Error("[PHYSICS]: MESH LOCKED"); + return; + } + if (IsPhysical && Body == (IntPtr) 0) + { + // Recreate the body + m_interpenetrationcount = 0; + m_collisionscore = 0; + + enableBody(); + + } + } + + public void ProcessTaints(float timestep) + { + + + if (m_taintadd) + { + changeadd(timestep); + } + + if (m_taintposition != _position) + Move(timestep); + + if (m_taintrot != _orientation) + rotate(timestep); + // + + if (m_taintPhysics != m_isphysical) + changePhysicsStatus(timestep); + // + + if (m_taintsize != _size) + changesize(timestep); + + if (m_BoundsScalingUpdate) // rex + changesize(timestep); + // + + if (m_taintshape) + changeshape(timestep); + // + + if (m_taintforce) + changeAddForce(timestep); + + if (m_taintdisable) + changedisable(timestep); + + if (m_taintVelocity != PhysicsVector.Zero) + changevelocity(timestep); + } + + public void ResetTaints() + { + + m_taintposition = _position; + + m_taintrot = _orientation; + + m_taintPhysics = m_isphysical; + + m_taintsize = _size; + + + m_taintshape = false; + + m_taintforce = false; + + m_taintdisable = false; + + m_taintVelocity = PhysicsVector.Zero; + } + public void changeadd(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position); + IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position); + + if (targetspace == IntPtr.Zero) + targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); + + m_targetSpace = targetspace; + + + + if (_mesh != null) + { + } + else + { + if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size); + // createmesh returns null when it's a shape that isn't a cube. + } + } + + lock (OdeScene.OdeLock) + { + if (_mesh != null) + { + setMesh(_parent_scene, _mesh); + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + if (((_size.X / 2f) > 0f)) + { + + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + //else if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + if (prim_geom != (IntPtr) 0) + { + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + + + if (m_isphysical && Body == (IntPtr)0) + { + enableBody(); + } + + + } + ode.dunlock(_parent_scene.world); + _parent_scene.geom_name_map[prim_geom] = this.m_primName; + _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; + m_taintadd = false; + + + } + public void Move(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + + if (m_isphysical) + { + // This is a fallback.. May no longer be necessary. + if (Body == (IntPtr) 0) + enableBody(); + //Prim auto disable after 20 frames, + //if you move it, re-enable the prim manually. + + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.BodyEnable(Body); + + } + else + { + string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); + int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); + _parent_scene.waitForSpaceUnlock(m_targetSpace); + + IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); + m_targetSpace = tempspace; + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + if (prim_geom != (IntPtr) 0) + { + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + d.SpaceAdd(m_targetSpace, prim_geom); + } + } + ode.dunlock(_parent_scene.world); + + resetCollisionAccounting(); + m_taintposition = _position; + } + + // rex, function changed + public void rotate(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + d.Quaternion myrot = new d.Quaternion(); + + if (m_DotMeshCollision && _mesh != null) // rex, setting rot for collision 3d model + { + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + + Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0)); + Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0)); + Quaternion mytemprot = _orientation * meshRotA * meshRotB; + + myrot.W = mytemprot.w; + myrot.X = mytemprot.x; + myrot.Y = mytemprot.y; + myrot.Z = mytemprot.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + else + { + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + + if (m_isphysical && Body != (IntPtr) 0) + { + d.BodySetQuaternion(Body, ref myrot); + } + + ode.dunlock(_parent_scene.world); + + resetCollisionAccounting(); + m_taintrot = _orientation; + } + + private void resetCollisionAccounting() + { + m_collisionscore = 0; + m_interpenetrationcount = 0; + m_disabled = false; + } + + public void changedisable(float timestep) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + m_disabled = true; + if (Body != (IntPtr)0) + { + d.BodyDisable(Body); + Body = (IntPtr)0; + } + ode.dunlock(_parent_scene.world); + + m_taintdisable = false; + } + + public void changePhysicsStatus(float timestap) + { + lock (ode) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + if (m_isphysical == true) + { + if (Body == (IntPtr)0) + { + enableBody(); + } + } + else + { + if (Body != (IntPtr)0) + { + disableBody(); + } + } + + ode.dunlock(_parent_scene.world); + } + + resetCollisionAccounting(); + m_taintPhysics = m_isphysical; + } + + // rex, function changed + public void changesize(float timestamp) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + //if (!_parent_scene.geom_name_map.ContainsKey(prim_geom)) + //{ + // m_taintsize = _size; + //return; + //} + string oldname = _parent_scene.geom_name_map[prim_geom]; + + + // Cleanup of old prim geometry + if (_mesh != null) + { + // Cleanup meshing here + } + //kill body to rebuild + if (IsPhysical && Body != (IntPtr) 0) + { + disableBody(); + } + if (d.SpaceQuery(m_targetSpace, prim_geom)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + d.SpaceRemove(m_targetSpace, prim_geom); + } + d.GeomDestroy(prim_geom); + prim_geom = (IntPtr)0; + // we don't need to do space calculation because the client sends a position update also. + + if (m_DotMeshCollision && _mesh != null) // rex, scaling dotmesh models + { + float[] scalefactor = new float[3]; + int vertindex = 0; + OdeCollisionMesh mesh = _mesh as OdeCollisionMesh; + + LLVector3 scalingvector = new LLVector3(_size.X, _size.Y, _size.Z); + if (mesh.m_BoundsScaling) + { + LLVector3 boundssize = mesh.BoundsMax - mesh.BoundsMin; + if (boundssize.X != 0) + scalingvector.X /= boundssize.X; + if (boundssize.Y != 0) + scalingvector.Z /= boundssize.Y; + if (boundssize.Z != 0) + scalingvector.Y /= boundssize.Z; + } + scalefactor[0] = scalingvector.X; + scalefactor[1] = scalingvector.Z; + scalefactor[2] = scalingvector.Y; + + for (int i = 0; i < mesh.vertexList.GetLength(0); i++) + { + mesh.vertexList[i] = mesh.vertexListOrig[i] * scalefactor[vertindex]; + vertindex++; + if (vertindex > 2) + vertindex = 0; + } + + for (int i = 0; i < mesh.indexList.GetLength(0); i++) + mesh.indexList[i] = mesh.indexListOrig[i]; + + setMesh(_parent_scene, mesh); + + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + + Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0)); + Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0)); + Quaternion mytemprot = _orientation * meshRotA * meshRotB; + + d.Quaternion myrot = new d.Quaternion(); + myrot.W = mytemprot.w; + myrot.X = mytemprot.x; + myrot.Y = mytemprot.y; + myrot.Z = mytemprot.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + if (IsPhysical && Body == (IntPtr)0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } // rex, end scaling + // Construction of new prim + else if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); + // createmesh returns null when it's a shape that isn't a cube. + if (mesh != null) + { + setMesh(_parent_scene, mesh); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr)0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + else + { + m_log.Info("[PHYSICS]: Failed to load a sphere bad size"); + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + } + //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + } + //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr) 0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + + _parent_scene.geom_name_map[prim_geom] = oldname; + + ode.dunlock(_parent_scene.world); + + resetCollisionAccounting(); + m_taintsize = _size; + m_BoundsScalingUpdate = false; // rex + } + + public void changeshape(float timestamp) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + + string oldname = _parent_scene.geom_name_map[prim_geom]; + + // Cleanup of old prim geometry and Bodies + if (IsPhysical && Body != (IntPtr) 0) + { + disableBody(); + } + d.GeomDestroy(prim_geom); + prim_geom = (IntPtr) 0; + // we don't need to do space calculation because the client sends a position update also. + + // Construction of new prim + if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); + // createmesh returns null when it's a shape that isn't a cube. + if (mesh != null) + { + setMesh(_parent_scene, mesh); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr)0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + else + { + m_log.Info("[PHYSICS]: Failed to load a sphere bad size"); + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + } + //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + } + //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight) + //{ + //Cyllinder + //if (_size.X == _size.Y) + //{ + //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z); + //} + //else + //{ + //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + //} + //} + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr)0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + _parent_scene.geom_name_map[prim_geom] = oldname; + + ode.dunlock(_parent_scene.world); + + resetCollisionAccounting(); + m_taintshape = false; + } + + public void changeAddForce(float timestamp) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + + lock (m_forcelist) + { + //m_log.Info("[PHYSICS]: dequeing forcelist"); + if (IsPhysical) + { + PhysicsVector iforce = new PhysicsVector(); + for (int i = 0; i < m_forcelist.Count; i++) + { + iforce = iforce + (m_forcelist[i]*100); + } + d.BodyEnable(Body); + d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); + } + m_forcelist.Clear(); + } + + ode.dunlock(_parent_scene.world); + + m_collisionscore = 0; + m_interpenetrationcount = 0; + m_taintforce = false; + + } + private void changevelocity(float timestep) + { + lock (ode) + { + while (ode.lockquery()) + { + } + ode.dlock(_parent_scene.world); + + System.Threading.Thread.Sleep(20); + if (IsPhysical) + { + if (Body != (IntPtr)0) + { + d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); + } + } + + ode.dunlock(_parent_scene.world); + } + //resetCollisionAccounting(); + m_taintVelocity = PhysicsVector.Zero; + } + public override bool IsPhysical + { + get { return m_isphysical; } + set { m_isphysical = value; } + } + + public void setPrimForRemoval() + { + m_taintremove = true; + } + + public override bool Flying + { + get { return false; //no flying prims for you + } + set { } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return m_throttleUpdates; } + set { m_throttleUpdates = value; } + } + + public override bool Stopped + { + get { return _zeroFlag; } + } + + public override PhysicsVector Position + { + get { return _position; } + + set { _position = value; + //m_log.Info("[PHYSICS]: " + _position.ToString()); + } + } + + public override PhysicsVector Size + { + get { return _size; } + set { _size = value; } + } + + public override float Mass + { + get { return CalculateMass(); } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { + + _pbs = value; + m_taintshape = true; + } + } + + public override PhysicsVector Velocity + { + get + { + // Averate previous velocity with the new one so + // client object interpolation works a 'little' better + PhysicsVector returnVelocity = new PhysicsVector(); + returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; + returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; + returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; + return returnVelocity; + } + set { + _velocity = value; + + m_taintVelocity = value; + _parent_scene.AddPhysicsActorTaint(this); + + + } + } + + public override float CollisionScore + { + get { return m_collisionscore; } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override Quaternion Orientation + { + get { return _orientation; } + set { _orientation = value; } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + m_forcelist.Add(force); + m_taintforce = true; + //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString()); + } + + public override PhysicsVector RotationalVelocity + { + get { + PhysicsVector pv = new PhysicsVector(0, 0, 0); + if (_zeroFlag) + return pv; + m_lastUpdateSent = false; + + if (m_rotationalVelocity.IsIdentical(pv, 0.2f)) + return pv; + + return m_rotationalVelocity; + } + set { m_rotationalVelocity = value; } + } + public override void CrossingFailure() + { + m_crossingfailures++; + if (m_crossingfailures > 5) + { + base.RaiseOutOfBounds(_position); + return; + + } + else if (m_crossingfailures == 5) + { + m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName); + } + } + public void UpdatePositionAndVelocity() + { + // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! + PhysicsVector pv = new PhysicsVector(0, 0, 0); + if (Body != (IntPtr) 0) + { + d.Vector3 vec = d.BodyGetPosition(Body); + d.Quaternion ori = d.BodyGetQuaternion(Body); + d.Vector3 vel = d.BodyGetLinearVel(Body); + d.Vector3 rotvel = d.BodyGetAngularVel(Body); + + PhysicsVector l_position = new PhysicsVector(); + + + // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) + //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + + m_lastposition = _position; + + l_position.X = vec.X; + l_position.Y = vec.Y; + l_position.Z = vec.Z; + + if (l_position.X > 255.95f || l_position.X < 0f || l_position.Y > 255.95f || l_position.Y < 0f) + { + base.RaiseOutOfBounds(_position); + } + //if (m_crossingfailures < 5) + //{ + //base.RequestPhysicsterseUpdate(); + //} + //} + + if (l_position.Z < 0) + { + // This is so prim that get lost underground don't fall forever and suck up + // + // Sim resources and memory. + // Disables the prim's movement physics.... + // It's a hack and will generate a console message if it fails. + + + //IsPhysical = false; + base.RaiseOutOfBounds(_position); + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + base.RequestPhysicsterseUpdate(); + m_throttleUpdates = false; + throttleCounter = 0; + _zeroFlag = true; + //outofBounds = true; + } + + if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) + && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) + && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)) + { + _zeroFlag = true; + m_throttleUpdates = false; + } + else + { + //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString()); + _zeroFlag = false; + } + + + if (_zeroFlag) + { + // Supposedly this is supposed to tell SceneObjectGroup that + // no more updates need to be sent.. + // but it seems broken. + _velocity.X = 0.0f; + _velocity.Y = 0.0f; + _velocity.Z = 0.0f; + //_orientation.w = 0f; + //_orientation.x = 0f; + //_orientation.y = 0f; + //_orientation.z = 0f; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + if (!m_lastUpdateSent) + { + m_throttleUpdates = false; + throttleCounter = 0; + m_rotationalVelocity = pv; + base.RequestPhysicsterseUpdate(); + m_lastUpdateSent = true; + } + } + else + { + m_lastVelocity = _velocity; + + _position = l_position; + + _velocity.X = vel.X; + _velocity.Y = vel.Y; + _velocity.Z = vel.Z; + if (_velocity.IsIdentical(pv, 0.5f)) + { + m_rotationalVelocity = pv; + } + else + { + m_rotationalVelocity.setValues(rotvel.X, rotvel.Y, rotvel.Z); + } + + //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString()); + _orientation.w = ori.W; + _orientation.x = ori.X; + _orientation.y = ori.Y; + _orientation.z = ori.Z; + m_lastUpdateSent = false; + if (!m_throttleUpdates || throttleCounter > 15) + { + + base.RequestPhysicsterseUpdate(); + } + else + { + throttleCounter++; + } + } + m_lastposition = l_position; + } + else + { + // Not a body.. so Make sure the client isn't interpolating + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + _zeroFlag = true; + } + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + + // rex, new function. + // This function should be called only outside of simulation loop -> OdeLock used. + public override void SetCollisionMesh(byte[] vData, string MeshName, bool vbScaleMesh) + { + float[] tempVertexList; + float[] tempBounds; + int[] tempIndexList; + string errorMessage; + float[] scalefactor = new float[3]; + int vertindex = 0; + + lock (OdeScene.OdeLock) + { + // 1. Get rid of old mesh + m_DotMeshCollision = false; + if (_mesh != null) + { + if ((OdeCollisionMesh)_mesh != null) + (_mesh as OdeCollisionMesh).FreeLists(); + + _mesh = null; + } + + // 2. Try to load new colmesh + OdeCollisionMesh mesh = null; + if (vData != null) + { + DotMeshLoader.ReadDotMeshModel(vData, out tempVertexList, out tempIndexList, out tempBounds, out errorMessage); + + if (tempVertexList != null && tempIndexList != null) + { + mesh = new OdeCollisionMesh(tempVertexList.GetLength(0), tempIndexList.GetLength(0)); + mesh.m_BoundsScaling = vbScaleMesh; + mesh.BoundsMin.X = tempBounds[0]; + mesh.BoundsMin.Y = tempBounds[1]; + mesh.BoundsMin.Z = tempBounds[2]; + mesh.BoundsMax.X = tempBounds[3]; + mesh.BoundsMax.Y = tempBounds[4]; + mesh.BoundsMax.Z = tempBounds[5]; + + LLVector3 scalingvector = new LLVector3(_size.X, _size.Y, _size.Z); + if (vbScaleMesh) + { + LLVector3 boundssize = mesh.BoundsMax - mesh.BoundsMin; + if (boundssize.X != 0) + scalingvector.X /= boundssize.X; + if (boundssize.Y != 0) + scalingvector.Z /= boundssize.Y; + if (boundssize.Z != 0) + scalingvector.Y /= boundssize.Z; + } + + scalefactor[0] = scalingvector.X; + scalefactor[1] = scalingvector.Z; + scalefactor[2] = scalingvector.Y; + for (int i = 0; i < tempVertexList.GetLength(0); i++) + { + mesh.vertexListOrig[i] = tempVertexList[i]; + mesh.vertexList[i] = tempVertexList[i] * scalefactor[vertindex]; + + vertindex++; + if (vertindex > 2) + vertindex = 0; + } + + for (int i = 0; i < tempIndexList.GetLength(0); i++) + { + mesh.indexListOrig[i] = tempIndexList[i]; + mesh.indexList[i] = tempIndexList[i]; + } + + + } + else + MainLog.Instance.Error("PHYSICS", "Error importing mesh:" + MeshName + ", " + errorMessage); + } + + // 3. If mesh is null, must create the default collisionbox + if (mesh == null) + { + CreateDefaultCollision(); + return; + } + + // 4. If mesh loaded, use it + string oldname = _parent_scene.geom_name_map[prim_geom]; + m_DotMeshCollision = true; + + if (IsPhysical && Body != (IntPtr)0) + disableBody(); + + if (prim_geom != (IntPtr)0) + { + if (d.SpaceQuery(m_targetSpace, prim_geom)) + { + d.SpaceRemove(m_targetSpace, prim_geom); + } + d.GeomDestroy(prim_geom); + } + + setMesh(_parent_scene, mesh); + + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + + Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0)); + Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0)); + Quaternion mytemprot = _orientation * meshRotA * meshRotB; + + d.Quaternion myrot = new d.Quaternion(); + myrot.W = mytemprot.w; + myrot.X = mytemprot.x; + myrot.Y = mytemprot.y; + myrot.Z = mytemprot.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + _parent_scene.geom_name_map[prim_geom] = oldname; + } + } + + + + + + // rex, function added + private void CreateDefaultCollision() + { + string oldname = _parent_scene.geom_name_map[prim_geom]; + + // Cleanup of old prim geometry + if (_mesh != null) + { + // Cleanup meshing here + } + //kill body to rebuild + if (IsPhysical && Body != (IntPtr)0) + { + disableBody(); + } + if (d.SpaceQuery(m_targetSpace, prim_geom)) + { + d.SpaceRemove(m_targetSpace, prim_geom); + } + d.GeomDestroy(prim_geom); + + // we don't need to do space calculation because the client sends a position update also. + // Construction of new prim + if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size); + // createmesh returns null when it's a shape that isn't a cube. + if (mesh != null) + { + setMesh(_parent_scene, mesh); + } + else + { + prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + } + else + { + prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.W = _orientation.w; + myrot.X = _orientation.x; + myrot.Y = _orientation.y; + myrot.Z = _orientation.z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == (IntPtr)0) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + } + _parent_scene.geom_name_map[prim_geom] = oldname; + } + + // rex, new function + public override void SetBoundsScaling(bool vbScaleMesh) + { + if (m_DotMeshCollision && _mesh != null) + { + (_mesh as OdeCollisionMesh).m_BoundsScaling = vbScaleMesh; + m_BoundsScalingUpdate = true; + } + } + + + + + } +} diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index f173a2a143..4e8945047c 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -1,1224 +1,1712 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using Axiom.Math; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Framework.Console; -using OpenSim.Region.Physics.Manager; - -//using OpenSim.Region.Physics.OdePlugin.Meshing; - -namespace OpenSim.Region.Physics.OdePlugin -{ - /// - /// ODE plugin - /// - public class OdePlugin : IPhysicsPlugin - { - private OdeScene _mScene; - - public OdePlugin() - { - } - - public bool Init() - { - return true; - } - - public PhysicsScene GetScene() - { - if (_mScene == null) - { - _mScene = new OdeScene(); - } - return (_mScene); - } - - public string GetName() - { - return ("OpenDynamicsEngine"); - } - - public void Dispose() - { - } - } - - public class OdeScene : PhysicsScene - { - // TODO: this should be hard-coded in some common place - private const uint m_regionWidth = 256; - private const uint m_regionHeight = 256; - - private static float ODE_STEPSIZE = 0.004f; - private static bool RENDER_FLAG = false; - private static float metersInSpace = 29.9f; - private IntPtr contactgroup; - private IntPtr LandGeom = (IntPtr) 0; - private double[] _heightmap; - private GCHandle gchHeightMap; // rex - private d.NearCallback nearCallback; - public d.TriCallback triCallback; - public d.TriArrayCallback triArrayCallback; - private List _characters = new List(); - private List _prims = new List(); - private List _activeprims = new List(); - private List _taintedPrim = new List(); - public Dictionary geom_name_map = new Dictionary(); - public Dictionary actor_name_map = new Dictionary(); - private d.ContactGeom[] contacts = new d.ContactGeom[30]; - private d.Contact contact; - private d.Contact TerrainContact; - private d.Contact AvatarMovementprimContact; - private d.Contact AvatarMovementTerrainContact; - - private int m_physicsiterations = 10; - private float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag - private PhysicsActor PANull = new NullPhysicsActor(); - private float step_time = 0.0f; - public IntPtr world; - - public IntPtr space; - // split static geometry collision handling into spaces of 30 meters - public IntPtr[,] staticPrimspace = new IntPtr[(int) (300/metersInSpace),(int) (300/metersInSpace)]; - - public static Object OdeLock = new Object(); - - public IMesher mesher; - - public OdeScene() - { - nearCallback = near; - triCallback = TriCallback; - triArrayCallback = TriArrayCallback; - /* - contact.surface.mode |= d.ContactFlags.Approx1 | d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP; - contact.surface.mu = 10.0f; - contact.surface.bounce = 0.9f; - contact.surface.soft_erp = 0.005f; - contact.surface.soft_cfm = 0.00003f; - */ - - contact.surface.mu = 250.0f; - contact.surface.bounce = 0.2f; - - TerrainContact.surface.mode |= d.ContactFlags.SoftERP; - TerrainContact.surface.mu = 550.0f; - TerrainContact.surface.bounce = 0.1f; - TerrainContact.surface.soft_erp = 0.1025f; - - AvatarMovementprimContact.surface.mu = 150.0f; - AvatarMovementprimContact.surface.bounce = 0.1f; - - AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; - AvatarMovementTerrainContact.surface.mu = 150.0f; - AvatarMovementTerrainContact.surface.bounce = 0.1f; - AvatarMovementTerrainContact.surface.soft_erp = 0.1025f; - - lock (OdeLock) - { - world = d.WorldCreate(); - space = d.HashSpaceCreate(IntPtr.Zero); - d.HashSpaceSetLevels(space, -4, 128); - contactgroup = d.JointGroupCreate(0); - //contactgroup - - - d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f); - d.WorldSetAutoDisableFlag(world, false); - d.WorldSetContactSurfaceLayer(world, 0.001f); - d.WorldSetQuickStepNumIterations(world, m_physicsiterations); - d.WorldSetContactMaxCorrectingVel(world, 1000.0f); - } - - _heightmap = new double[514*514]; - gchHeightMap = GCHandle.Alloc(_heightmap, GCHandleType.Pinned); // rex - - for (int i = 0; i < staticPrimspace.GetLength(0); i++) - { - for (int j = 0; j < staticPrimspace.GetLength(1); j++) - { - staticPrimspace[i, j] = IntPtr.Zero; - } - } - } - - public override void Initialise(IMesher meshmerizer) - { - mesher = meshmerizer; - } - - public string whichspaceamIin(PhysicsVector pos) - { - return calculateSpaceForGeom(pos).ToString(); - } - - private void near(IntPtr space, IntPtr g1, IntPtr g2) - { - // no lock here! It's invoked from within Simulate(), which is thread-locked - if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) - { - // Separating static prim geometry spaces. - // We'll be calling near recursivly if one - // of them is a space to find all of the - // contact points in the space - - d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); - //Colliding a space or a geom with a space or a geom. - - //Collide all geoms in each space.. - //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); - //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); - } - else - { - // Colliding Geom To Geom - // This portion of the function 'was' blatantly ripped off from BoxStack.cs - - IntPtr b1 = d.GeomGetBody(g1); - IntPtr b2 = d.GeomGetBody(g2); - - if (g1 == g2) - return; // Can't collide with yourself - - if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) - return; - - d.GeomClassID id = d.GeomGetClass(g1); - - String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(g1, out name1)) - { - name1 = "null"; - } - if (!geom_name_map.TryGetValue(g2, out name2)) - { - name2 = "null"; - } - - if (id == d.GeomClassID.TriMeshClass) - { - // MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2); - //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); - } - - int count = 0; - try - { - count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); - } - catch (SEHException) - { - MainLog.Instance.Error("PHYSICS", - "The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); - base.TriggerPhysicsBasedRestart(); - } - - for (int i = 0; i < count; i++) - { - IntPtr joint; - // If we're colliding with terrain, use 'TerrainContact' instead of contact. - // allows us to have different settings - PhysicsActor p1; - PhysicsActor p2; - - if (!actor_name_map.TryGetValue(g1, out p1)) - { - p1 = PANull; - } - if (!actor_name_map.TryGetValue(g2, out p2)) - { - p2 = PANull; - } - - // We only need to test p2 for 'jump crouch purposes' - p2.IsColliding = true; - - - switch (p1.PhysicsActorType) - { - case (int) ActorTypes.Agent: - p2.CollidingObj = true; - break; - case (int) ActorTypes.Prim: - if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) - p2.CollidingObj = true; - break; - case (int) ActorTypes.Unknown: - p2.CollidingGround = true; - break; - case (int)ActorTypes.PrimVolume: // rex, added primvolume - if (Util.UnixTimeSinceEpoch() > p2.NextPrimVolumeTime) - { - p2.NextPrimVolumeTime = Util.UnixTimeSinceEpoch() + 1; - p1.SendCollisionUpdate(new CollisionEventUpdate(p2.m_localID,0,true,null)); - } - return; - default: - p2.CollidingGround = true; - break; - } - // we don't want prim or avatar to explode - - #region InterPenetration Handling - Unintended physics explosions - - if (contacts[i].depth >= 0.08f) - { - if (contacts[i].depth >= 1.00f) - { - //MainLog.Instance.Debug("PHYSICS",contacts[i].depth.ToString()); - } - // If you interpenetrate a prim with an agent - if ((p2.PhysicsActorType == (int) ActorTypes.Agent && - p1.PhysicsActorType == (int) ActorTypes.Prim) || - (p1.PhysicsActorType == (int) ActorTypes.Agent && - p2.PhysicsActorType == (int) ActorTypes.Prim)) - { - if (p2.PhysicsActorType == (int) ActorTypes.Agent) - { - //p2.CollidingObj = true; - //contacts[i].depth = 0.003f; - //p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); - //OdeCharacter character = (OdeCharacter) p2; - //character.SetPidStatus(true); - //contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); - - } - else - { - - //contacts[i].depth = 0.0000000f; - } - if (p1.PhysicsActorType == (int) ActorTypes.Agent) - { - - //p1.CollidingObj = true; - //contacts[i].depth = 0.003f; - //p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); - //contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); - //OdeCharacter character = (OdeCharacter)p1; - //character.SetPidStatus(true); - } - else - { - - //contacts[i].depth = 0.0000000f; - } - } - // If you interpenetrate a prim with another prim - if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) - { - // Don't collide, one or both prim will explode. - contacts[i].depth = 0f; - } - if (contacts[i].depth >= 1.00f) - { - if ((p2.PhysicsActorType == (int) ActorTypes.Agent && - p1.PhysicsActorType == (int) ActorTypes.Unknown) || - (p1.PhysicsActorType == (int) ActorTypes.Agent && - p2.PhysicsActorType == (int) ActorTypes.Unknown)) - { - if (p2.PhysicsActorType == (int) ActorTypes.Agent) - { - OdeCharacter character = (OdeCharacter) p2; - - //p2.CollidingObj = true; - contacts[i].depth = 0.003f; - p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f); - contacts[i].pos = - new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), - contacts[i].pos.Y + (p1.Size.Y/2), - contacts[i].pos.Z + (p1.Size.Z/2)); - character.SetPidStatus(true); - } - else - { - } - if (p1.PhysicsActorType == (int) ActorTypes.Agent) - { - OdeCharacter character = (OdeCharacter)p1; - - //p2.CollidingObj = true; - contacts[i].depth = 0.003f; - p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f); - contacts[i].pos = - new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), - contacts[i].pos.Y + (p1.Size.Y/2), - contacts[i].pos.Z + (p1.Size.Z/2)); - character.SetPidStatus(true); - } - else - { - //contacts[i].depth = 0.0000000f; - } - } - } - } - - #endregion - - if (contacts[i].depth >= 0f) - { - if (name1 == "Terrain" || name2 == "Terrain") - { - if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && - (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) - { - AvatarMovementTerrainContact.geom = contacts[i]; - joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); - } - else - { - TerrainContact.geom = contacts[i]; - joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); - } - } - else - { - if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && - (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) - { - AvatarMovementprimContact.geom = contacts[i]; - joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); - } - else - { - contact.geom = contacts[i]; - joint = d.JointCreateContact(world, contactgroup, ref contact); - } - } - d.JointAttach(joint, b1, b2); - } - - if (count > 3) - { - p2.ThrottleUpdates = true; - } - //System.Console.WriteLine(count.ToString()); - //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); - } - } - } - - private void collision_optimized(float timeStep) - { - foreach (OdeCharacter chr in _characters) - { - chr.IsColliding = false; - chr.CollidingGround = false; - chr.CollidingObj = false; - d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); - } - // If the sim is running slow this frame, - // don't process collision for prim! - if (timeStep < (m_SkipFramesAtms/3)) - { - foreach (OdePrim chr in _activeprims) - { - // This if may not need to be there.. it might be skipped anyway. - if (d.BodyIsEnabled(chr.Body)) - { - d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); - //foreach (OdePrim ch2 in _prims) - /// should be a separate space -- lots of avatars will be N**2 slow - //{ - //if (ch2.IsPhysical && d.BodyIsEnabled(ch2.Body)) - //{ - // Only test prim that are 0.03 meters away in one direction. - // This should be Optimized! - - //if ((Math.Abs(ch2.Position.X - chr.Position.X) < 0.03) || (Math.Abs(ch2.Position.Y - chr.Position.Y) < 0.03) || (Math.Abs(ch2.Position.X - chr.Position.X) < 0.03)) - //{ - //d.SpaceCollide2(chr.prim_geom, ch2.prim_geom, IntPtr.Zero, nearCallback); - //} - //} - //} - } - } - } - else - { - // Everything is going slow, so we're skipping object to object collisions - // At least collide test against the ground. - foreach (OdePrim chr in _activeprims) - { - // This if may not need to be there.. it might be skipped anyway. - if (d.BodyIsEnabled(chr.Body)) - { - d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback); - } - } - } - } - - public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID) // rex, localid - { - PhysicsVector pos = new PhysicsVector(); - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z; - OdeCharacter newAv = new OdeCharacter(avName, this, pos, localID); // rex, localid - _characters.Add(newAv); - - return newAv; - } - - public override void RemoveAvatar(PhysicsActor actor) - { - lock (OdeLock) - { - ((OdeCharacter) actor).Destroy(); - _characters.Remove((OdeCharacter) actor); - } - } - - public override void RemovePrim(PhysicsActor prim) - { - if (prim is OdePrim) - { - lock (OdeLock) - { - OdePrim p = (OdePrim) prim; - - p.setPrimForRemoval(); - AddPhysicsActorTaint(prim); - } - } - } - - public void RemovePrimThreadLocked(OdePrim prim) - { - lock (OdeLock) - { - if (prim.IsPhysical) - { - prim.disableBody(); - } - // we don't want to remove the main space - if (prim.m_targetSpace != space && prim.IsPhysical == false) - { - // If the geometry is in the targetspace, remove it from the target space - if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom)) - { - if (!(prim.m_targetSpace.Equals(null))) - { - if (d.GeomIsSpace(prim.m_targetSpace)) - { - d.SpaceRemove(prim.m_targetSpace, prim.prim_geom); - } - else - { - MainLog.Instance.Verbose("Physics", - "Invalid Scene passed to 'removeprim from scene':" + - ((OdePrim) prim).m_targetSpace.ToString()); - } - } - } - - - //If there are no more geometries in the sub-space, we don't need it in the main space anymore - if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) - { - if (!(prim.m_targetSpace.Equals(null))) - { - if (d.GeomIsSpace(prim.m_targetSpace)) - { - d.SpaceRemove(space, prim.m_targetSpace); - // free up memory used by the space. - d.SpaceDestroy(prim.m_targetSpace); - int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position); - resetSpaceArrayItemToZero(xyspace[0], xyspace[1]); - } - else - { - MainLog.Instance.Verbose("Physics", - "Invalid Scene passed to 'removeprim from scene':" + - ((OdePrim) prim).m_targetSpace.ToString()); - } - } - } - } - - d.GeomDestroy(prim.prim_geom); - - _prims.Remove(prim); - } - } - - public void resetSpaceArrayItemToZero(IntPtr space) - { - for (int x = 0; x < staticPrimspace.GetLength(0); x++) - { - for (int y = 0; y < staticPrimspace.GetLength(1); y++) - { - if (staticPrimspace[x, y] == space) - staticPrimspace[x, y] = IntPtr.Zero; - } - } - } - - public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY) - { - staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; - } - - public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos, IntPtr currentspace) - { - //Todo recalculate space the prim is in. - // Called from setting the Position and Size of an ODEPrim so - // it's already in locked space. - - // we don't want to remove the main space - // we don't need to test physical here because this function should - // never be called if the prim is physical(active) - if (currentspace != space) - { - if (d.SpaceQuery(currentspace, geom) && currentspace != (IntPtr) 0) - { - if (d.GeomIsSpace(currentspace)) - { - d.SpaceRemove(currentspace, geom); - } - else - { - MainLog.Instance.Verbose("Physics", - "Invalid Scene passed to 'recalculatespace':" + currentspace.ToString() + - " Geom:" + geom.ToString()); - } - } - else - { - IntPtr sGeomIsIn = d.GeomGetSpace(geom); - if (!(sGeomIsIn.Equals(null))) - { - if (sGeomIsIn != (IntPtr) 0) - { - if (d.GeomIsSpace(currentspace)) - { - d.SpaceRemove(sGeomIsIn, geom); - } - else - { - MainLog.Instance.Verbose("Physics", - "Invalid Scene passed to 'recalculatespace':" + - sGeomIsIn.ToString() + " Geom:" + geom.ToString()); - } - } - } - } - - - //If there are no more geometries in the sub-space, we don't need it in the main space anymore - if (d.SpaceGetNumGeoms(currentspace) == 0) - { - if (currentspace != (IntPtr) 0) - { - if (d.GeomIsSpace(currentspace)) - { - d.SpaceRemove(space, currentspace); - // free up memory used by the space. - d.SpaceDestroy(currentspace); - resetSpaceArrayItemToZero(currentspace); - } - else - { - MainLog.Instance.Verbose("Physics", - "Invalid Scene passed to 'recalculatespace':" + - currentspace.ToString() + " Geom:" + geom.ToString()); - } - } - } - } - else - { - // this is a physical object that got disabled. ;.; - if (d.SpaceQuery(currentspace, geom)) - { - if (currentspace != (IntPtr) 0) - if (d.GeomIsSpace(currentspace)) - { - d.SpaceRemove(currentspace, geom); - } - else - { - MainLog.Instance.Verbose("Physics", - "Invalid Scene passed to 'recalculatespace':" + - currentspace.ToString() + " Geom:" + geom.ToString()); - } - } - else - { - IntPtr sGeomIsIn = d.GeomGetSpace(geom); - if (!(sGeomIsIn.Equals(null))) - { - if (sGeomIsIn != (IntPtr) 0) - { - if (d.GeomIsSpace(sGeomIsIn)) - { - d.SpaceRemove(sGeomIsIn, geom); - } - else - { - MainLog.Instance.Verbose("Physics", - "Invalid Scene passed to 'recalculatespace':" + - sGeomIsIn.ToString() + " Geom:" + geom.ToString()); - } - } - } - } - } - - - // The routines in the Position and Size sections do the 'inserting' into the space, - // so all we have to do is make sure that the space that we're putting the prim into - // is in the 'main' space. - int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos); - IntPtr newspace = calculateSpaceForGeom(pos); - - if (newspace == IntPtr.Zero) - { - newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); - d.HashSpaceSetLevels(newspace, -4, 66); - } - - return newspace; - } - - public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) - { - // creating a new space for prim and inserting it into main space. - staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); - d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); - return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; - } - - public IntPtr calculateSpaceForGeom(PhysicsVector pos) - { - int[] xyspace = calculateSpaceArrayItemFromPos(pos); - //MainLog.Instance.Verbose("Physics", "Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString()); - IntPtr locationbasedspace = staticPrimspace[xyspace[0], xyspace[1]]; - - //locationbasedspace = space; - return locationbasedspace; - } - - public int[] calculateSpaceArrayItemFromPos(PhysicsVector pos) - { - int[] returnint = new int[2]; - - returnint[0] = (int) (pos.X/metersInSpace); - - if (returnint[0] > ((int) (259f/metersInSpace))) - returnint[0] = ((int) (259f/metersInSpace)); - if (returnint[0] < 0) - returnint[0] = 0; - - returnint[1] = (int) (pos.Y/metersInSpace); - if (returnint[0] > ((int) (259f/metersInSpace))) - returnint[0] = ((int) (259f/metersInSpace)); - if (returnint[0] < 0) - returnint[0] = 0; - - return returnint; - } - - private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, - IMesh mesh, PrimitiveBaseShape pbs, bool isphysical, uint localID) // rex, localid - { - PhysicsVector pos = new PhysicsVector(); - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z; - PhysicsVector siz = new PhysicsVector(); - siz.X = size.X; - siz.Y = size.Y; - siz.Z = size.Z; - Quaternion rot = new Quaternion(); - rot.w = rotation.w; - rot.x = rotation.x; - rot.y = rotation.y; - rot.z = rotation.z; - - - int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos); - IntPtr targetspace = calculateSpaceForGeom(pos); - - if (targetspace == IntPtr.Zero) - targetspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); - - OdePrim newPrim; - lock (OdeLock) - { - newPrim = new OdePrim(name, this, targetspace, pos, siz, rot, mesh, pbs, isphysical, localID); // rex, localid - - _prims.Add(newPrim); - } - - return newPrim; - } - - public void addActivePrim(OdePrim activatePrim) - { - // adds active prim.. (ones that should be iterated over in collisions_optimized - - _activeprims.Add(activatePrim); - } - - public void remActivePrim(OdePrim deactivatePrim) - { - _activeprims.Remove(deactivatePrim); - } - - public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) - { -/* String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(trimesh, out name1)) - { - name1 = "null"; - } - if (!geom_name_map.TryGetValue(refObject, out name2)) - { - name2 = "null"; - } - - MainLog.Instance.Verbose("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); -*/ - return 1; - } - - public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) - { - String name1 = null; - String name2 = null; - - if (!geom_name_map.TryGetValue(trimesh, out name1)) - { - name1 = "null"; - } - if (!geom_name_map.TryGetValue(refObject, out name2)) - { - name2 = "null"; - } - -// MainLog.Instance.Verbose("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); - - d.Vector3 v0 = new d.Vector3(); - d.Vector3 v1 = new d.Vector3(); - d.Vector3 v2 = new d.Vector3(); - - d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); -// MainLog.Instance.Debug("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); - - return 1; - } - - - public bool needsMeshing(PrimitiveBaseShape pbs) - { - if (pbs.ProfileHollow != 0) - return true; - - if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) - return true; - - return false; - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, uint localID) //To be removed rex, localid - { - return AddPrimShape(primName, pbs, position, size, rotation, false,localID); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) // rex, localid - { - PhysicsActor result; - IMesh mesh = null; - - switch (pbs.ProfileShape) - { - case ProfileShape.Square: - /// support simple box & hollow box now; later, more shapes - if (needsMeshing(pbs)) - { - mesh = mesher.CreateMesh(primName, pbs, size); - } - - break; - } - - result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, localID); // rex, localid - - - return result; - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - if (prim is OdePrim) - { - OdePrim taintedprim = ((OdePrim) prim); - if (!(_taintedPrim.Contains(taintedprim))) - _taintedPrim.Add(taintedprim); - } - } - - public override float Simulate(float timeStep) - { - float fps = 0; - - step_time += timeStep; - - - // If We're loaded down by something else, - // or debugging with the Visual Studio project on pause - // skip a few frames to catch up gracefully. - // without shooting the physicsactors all over the place - - - if (step_time >= m_SkipFramesAtms) - { - // Instead of trying to catch up, it'll do one physics frame only - step_time = ODE_STEPSIZE; - m_physicsiterations = 5; - } - else - { - m_physicsiterations = 10; - } - lock (OdeLock) - { - // Process 10 frames if the sim is running normal.. - // process 5 frames if the sim is running slow - try - { - d.WorldSetQuickStepNumIterations(world, m_physicsiterations); - } - catch (StackOverflowException) - { - MainLog.Instance.Error("PHYSICS", - "The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); - base.TriggerPhysicsBasedRestart(); - } - - int i = 0; - - - // Figure out the Frames Per Second we're going at. - - fps = (((step_time/ODE_STEPSIZE*m_physicsiterations)*2)*10); - - - while (step_time > 0.0f) - { - foreach (OdeCharacter actor in _characters) - { - actor.Move(timeStep); - actor.collidelock = true; - } - - - collision_optimized(timeStep); - d.WorldQuickStep(world, ODE_STEPSIZE); - d.JointGroupEmpty(contactgroup); - foreach (OdeCharacter actor in _characters) - { - actor.collidelock = false; - } - - step_time -= ODE_STEPSIZE; - i++; - } - - foreach (OdeCharacter actor in _characters) - { - actor.UpdatePositionAndVelocity(); - } - bool processedtaints = false; - foreach (OdePrim prim in _taintedPrim) - { - prim.ProcessTaints(timeStep); - if (prim.m_taintremove) - { - RemovePrimThreadLocked(prim); - } - processedtaints = true; - } - if (processedtaints) - _taintedPrim = new List(); - - if (timeStep < 0.2f) - { - foreach (OdePrim actor in _activeprims) - { - if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) - { - actor.UpdatePositionAndVelocity(); - } - } - } - } - return fps; - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - get { return (false); // for now we won't be multithreaded - } - } - - public float[] ResizeTerrain512(float[] heightMap) - { - float[] returnarr = new float[262144]; - float[,] resultarr = new float[m_regionWidth,m_regionHeight]; - - // Filling out the array into it's multi-dimentional components - for (int y = 0; y < m_regionHeight; y++) - { - for (int x = 0; x < m_regionWidth; x++) - { - resultarr[y, x] = heightMap[y*m_regionWidth + x]; - } - } - - // Resize using interpolation - - // This particular way is quick but it only works on a multiple of the original - - // The idea behind this method can be described with the following diagrams - // second pass and third pass happen in the same loop really.. just separated - // them to show what this does. - - // First Pass - // ResultArr: - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - // 1,1,1,1,1,1 - - // Second Pass - // ResultArr2: - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - // ,,,,,,,,,, - // 1,,1,,1,,1,,1,,1, - - // Third pass fills in the blanks - // ResultArr2: - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - // 1,1,1,1,1,1,1,1,1,1,1,1 - - // X,Y = . - // X+1,y = ^ - // X,Y+1 = * - // X+1,Y+1 = # - - // Filling in like this; - // .* - // ^# - // 1st . - // 2nd * - // 3rd ^ - // 4th # - // on single loop. - - float[,] resultarr2 = new float[512,512]; - for (int y = 0; y < m_regionHeight; y++) - { - for (int x = 0; x < m_regionWidth; x++) - { - resultarr2[y*2, x*2] = resultarr[y, x]; - - if (y < m_regionHeight) - { - if (y + 1 < m_regionHeight) - { - if (x + 1 < m_regionWidth) - { - resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2); - } - } - else - { - resultarr2[(y*2) + 1, x*2] = resultarr[y, x]; - } - } - if (x < m_regionWidth) - { - if (x + 1 < m_regionWidth) - { - if (y + 1 < m_regionHeight) - { - resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2); - } - } - else - { - resultarr2[y*2, (x*2) + 1] = resultarr[y, x]; - } - } - if (x < m_regionWidth && y < m_regionHeight) - { - if ((x + 1 < m_regionWidth) && (y + 1 < m_regionHeight)) - { - resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + - resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); - } - else - { - resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x]; - } - } - } - } - //Flatten out the array - int i = 0; - for (int y = 0; y < 512; y++) - { - for (int x = 0; x < 512; x++) - { - if (resultarr2[y, x] <= 0) - returnarr[i] = 0.0000001f; - else - returnarr[i] = resultarr2[y, x]; - - i++; - } - } - - return returnarr; - } - - public override void SetTerrain(float[] heightMap) - { - // this._heightmap[i] = (double)heightMap[i]; - // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) - // also, creating a buffer zone of one extra sample all around - - const uint heightmapWidth = m_regionWidth + 2; - const uint heightmapHeight = m_regionHeight + 2; - const uint heightmapWidthSamples = 2*m_regionWidth + 2; - const uint heightmapHeightSamples = 2*m_regionHeight + 2; - const float scale = 1.0f; - const float offset = 0.0f; - const float thickness = 2.0f; - const int wrap = 0; - - //Double resolution - heightMap = ResizeTerrain512(heightMap); - for (int x = 0; x < heightmapWidthSamples; x++) - { - for (int y = 0; y < heightmapHeightSamples; y++) - { - int xx = Util.Clip(x - 1, 0, 511); - int yy = Util.Clip(y - 1, 0, 511); - - double val = (double) heightMap[yy*512 + xx]; - _heightmap[x*heightmapHeightSamples + y] = val; - } - } - - lock (OdeLock) - { - if (!(LandGeom == (IntPtr) 0)) - { - d.SpaceRemove(space, LandGeom); - } - IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); - d.GeomHeightfieldDataBuildDouble(HeightmapData, _heightmap, 0, heightmapWidth, heightmapHeight, - (int) heightmapWidthSamples, (int) heightmapHeightSamples, scale, - offset, thickness, wrap); - d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); - LandGeom = d.CreateHeightfield(space, HeightmapData, 1); - geom_name_map[LandGeom] = "Terrain"; - - d.Matrix3 R = new d.Matrix3(); - - Quaternion q1 = Quaternion.FromAngleAxis(1.5707f, new Vector3(1, 0, 0)); - Quaternion q2 = Quaternion.FromAngleAxis(1.5707f, new Vector3(0, 1, 0)); - //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); - - q1 = q1*q2; - //q1 = q1 * q3; - Vector3 v3 = new Vector3(); - float angle = 0; - q1.ToAngleAxis(ref angle, ref v3); - - d.RFromAxisAndAngle(out R, v3.x, v3.y, v3.z, angle); - d.GeomSetRotation(LandGeom, ref R); - d.GeomSetPosition(LandGeom, 128, 128, 0); - } - } - - public override void DeleteTerrain() - { - } - } -} +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Axiom.Math; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Physics.Manager; + +//using OpenSim.Region.Physics.OdePlugin.Meshing; + +namespace OpenSim.Region.Physics.OdePlugin +{ + /// + /// ODE plugin + /// + public class OdePlugin : IPhysicsPlugin + { + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private CollisionLocker ode; + private OdeScene _mScene; + + public OdePlugin() + { + ode = new CollisionLocker(); + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + if (_mScene == null) + { + _mScene = new OdeScene(ode); + } + return (_mScene); + } + + public string GetName() + { + return ("OpenDynamicsEngine"); + } + + public void Dispose() + { + } + } + + public class OdeScene : PhysicsScene + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + CollisionLocker ode; + + private const uint m_regionWidth = Constants.RegionSize; + private const uint m_regionHeight = Constants.RegionSize; + + private static float ODE_STEPSIZE = 0.020f; + private static bool RENDER_FLAG = false; + private static float metersInSpace = 29.9f; + + private int interpenetrations_before_disable = 35; + + private IntPtr contactgroup; + private IntPtr LandGeom = (IntPtr) 0; + private float[] _heightmap; + private float[] _origheightmap; + + private GCHandle gchHeightMap; // rex + private d.NearCallback nearCallback; + public d.TriCallback triCallback; + public d.TriArrayCallback triArrayCallback; + private List _characters = new List(); + private List _prims = new List(); + private List _activeprims = new List(); + private List _taintedPrim = new List(); + public Dictionary geom_name_map = new Dictionary(); + public Dictionary actor_name_map = new Dictionary(); + private d.ContactGeom[] contacts = new d.ContactGeom[30]; + private d.Contact contact; + private d.Contact TerrainContact; + private d.Contact AvatarMovementprimContact; + private d.Contact AvatarMovementTerrainContact; + + + + private int m_physicsiterations = 10; + private float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag + private PhysicsActor PANull = new NullPhysicsActor(); + private float step_time = 0.0f; + private int ms = 0; + public IntPtr world; + + public IntPtr space; + + private IntPtr tmpSpace; + // split static geometry collision handling into spaces of 30 meters + public IntPtr[,] staticPrimspace = new IntPtr[(int) (300/metersInSpace),(int) (300/metersInSpace)]; + + public static Object OdeLock = new Object(); + + public IMesher mesher; + + + /// + /// Initiailizes the scene + /// Sets many properties that ODE requires to be stable + /// These settings need to be tweaked 'exactly' right or weird stuff happens. + /// + public OdeScene(CollisionLocker dode) + { + ode = dode; + nearCallback = near; + triCallback = TriCallback; + triArrayCallback = TriArrayCallback; + /* + contact.surface.mode |= d.ContactFlags.Approx1 | d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP; + contact.surface.mu = 10.0f; + contact.surface.bounce = 0.9f; + contact.surface.soft_erp = 0.005f; + contact.surface.soft_cfm = 0.00003f; + */ + + // Centeral contact friction and bounce + contact.surface.mu = 250.0f; + contact.surface.bounce = 0.2f; + + // Terrain contact friction and Bounce + // This is the *non* moving version. Use this when an avatar + // isn't moving to keep it in place better + TerrainContact.surface.mode |= d.ContactFlags.SoftERP; + TerrainContact.surface.mu = 255.0f; + TerrainContact.surface.bounce = 0.1f; + TerrainContact.surface.soft_erp = 0.1025f; + + // Prim contact friction and bounce + // THis is the *non* moving version of friction and bounce + // Use this when an avatar comes in contact with a prim + // and is moving + AvatarMovementprimContact.surface.mu = 75.0f; + AvatarMovementprimContact.surface.bounce = 0.1f; + + // Terrain contact friction bounce and various error correcting calculations + // Use this when an avatar is in contact with the terrain and moving. + AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; + AvatarMovementTerrainContact.surface.mu = 75.0f; + AvatarMovementTerrainContact.surface.bounce = 0.1f; + AvatarMovementTerrainContact.surface.soft_erp = 0.1025f; + + lock (OdeLock) + { + + // Creat the world and the first space + world = d.WorldCreate(); + space = d.HashSpaceCreate(IntPtr.Zero); + d.HashSpaceSetLevels(space, -4, 128); + contactgroup = d.JointGroupCreate(0); + //contactgroup + + + // Set the gravity,, don't disable things automatically (we set it explicitly on some things) + + d.WorldSetGravity(world, 0.0f, 0.0f, -9.8f); + d.WorldSetAutoDisableFlag(world, false); + d.WorldSetContactSurfaceLayer(world, 0.001f); + + // Set how many steps we go without running collision testing + // This is in addition to the step size. + // Essentially Steps * m_physicsiterations + d.WorldSetQuickStepNumIterations(world, m_physicsiterations); + ///d.WorldSetContactMaxCorrectingVel(world, 1000.0f); + } + + // zero out a heightmap array float array (single dimention [flattened])) + _heightmap = new float[514*514]; + gchHeightMap = GCHandle.Alloc(_heightmap, GCHandleType.Pinned); // rex + + + // Zero out the prim spaces array (we split our space into smaller spaces so + // we can hit test less. + for (int i = 0; i < staticPrimspace.GetLength(0); i++) + { + for (int j = 0; j < staticPrimspace.GetLength(1); j++) + { + staticPrimspace[i, j] = IntPtr.Zero; + } + } + } + + public void starttiming() + { + ms = Environment.TickCount; + } + public int stoptiming() + { + return Environment.TickCount - ms; + } + // Initialize the mesh plugin + public override void Initialise(IMesher meshmerizer) + { + mesher = meshmerizer; + } + + internal void waitForSpaceUnlock(IntPtr space) + { + + while (d.SpaceLockQuery(space)) + { + + } + + + + } + /// + /// Debug space message for printing the space that a prim/avatar is in. + /// + /// + /// Returns which split up space the given position is in. + public string whichspaceamIin(PhysicsVector pos) + { + return calculateSpaceForGeom(pos).ToString(); + } + + /// + /// This is our near callback. A geometry is near a body + /// + /// The space that contains the geoms. Remember, spaces are also geoms + /// a geometry or space + /// another geometry or space + private void near(IntPtr space, IntPtr g1, IntPtr g2) + { + // no lock here! It's invoked from within Simulate(), which is thread-locked + + // Test if we're collidng a geom with a space. + // If so we have to drill down into the space recursively + + if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) + { + if (g1 == (IntPtr)0 || g2 == (IntPtr)0) + return; + // Separating static prim geometry spaces. + // We'll be calling near recursivly if one + // of them is a space to find all of the + // contact points in the space + try + { + d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); + } + catch (System.AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to collide test a space"); + return; + } + //Colliding a space or a geom with a space or a geom. so drill down + + //Collide all geoms in each space.. + //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); + //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); + } + else + { + // Colliding Geom To Geom + // This portion of the function 'was' blatantly ripped off from BoxStack.cs + if (g1 == (IntPtr)0 || g2 == (IntPtr)0) + return; + + IntPtr b1 = d.GeomGetBody(g1); + IntPtr b2 = d.GeomGetBody(g2); + + if (g1 == g2) + return; // Can't collide with yourself + + if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) + return; + + + + d.GeomClassID id = d.GeomGetClass(g1); + + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(g1, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(g2, out name2)) + { + name2 = "null"; + } + + //if (id == d.GeomClassId.TriMeshClass) + //{ + // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2); + //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); + //} + + // Figure out how many contact points we have + int count = 0; + try + { + //m_log.Warn(g1.ToString() + "|" + g2.ToString()); + count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); + } + catch (SEHException) + { + m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); + ode.drelease(world); + base.TriggerPhysicsBasedRestart(); + } + catch (System.AccessViolationException) + { + + m_log.Warn("[PHYSICS]: Unable to collide test an object"); + return; + } + + PhysicsActor p1; + PhysicsActor p2; + + for (int i = 0; i < count; i++) + { + //m_log.Warn("[CCOUNT]: " + count); + IntPtr joint; + // If we're colliding with terrain, use 'TerrainContact' instead of contact. + // allows us to have different settings + + if (!actor_name_map.TryGetValue(g1, out p1)) + { + p1 = PANull; + } + if (!actor_name_map.TryGetValue(g2, out p2)) + { + p2 = PANull; + } + + // We only need to test p2 for 'jump crouch purposes' + p2.IsColliding = true; + + + switch (p1.PhysicsActorType) + { + case (int)ActorTypes.Agent: + p2.CollidingObj = true; + break; + case (int)ActorTypes.Prim: + if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) + p2.CollidingObj = true; + break; + case (int)ActorTypes.Unknown: + p2.CollidingGround = true; + break; + case (int)ActorTypes.PrimVolume: // rex, added primvolume + if (Util.UnixTimeSinceEpoch() > p2.NextPrimVolumeTime) + { + p2.NextPrimVolumeTime = Util.UnixTimeSinceEpoch() + 1; + p1.SendCollisionUpdate(new CollisionEventUpdate(p2.m_localID,0,true,null)); + } + return; + default: + p2.CollidingGround = true; + break; + } + // we don't want prim or avatar to explode + + #region InterPenetration Handling - Unintended physics explosions + + if (contacts[i].depth >= 0.08f) + { + //This is disabled at the moment only because it needs more tweaking + //It will eventually be uncommented + + if (contacts[i].depth >= 1.00f) + { + //m_log.Debug("[PHYSICS]: " + contacts[i].depth.ToString()); + } + + //If you interpenetrate a prim with an agent + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Prim) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Prim)) + { + //contacts[i].depth = contacts[i].depth * 4.15f; + /* + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + p2.CollidingObj = true; + contacts[i].depth = 0.003f; + p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); + OdeCharacter character = (OdeCharacter) p2; + character.SetPidStatus(true); + contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); + + } + else + { + + //contacts[i].depth = 0.0000000f; + } + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + + p1.CollidingObj = true; + contacts[i].depth = 0.003f; + p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); + contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); + OdeCharacter character = (OdeCharacter)p1; + character.SetPidStatus(true); + } + else + { + + //contacts[i].depth = 0.0000000f; + } + */ + } + + + // If you interpenetrate a prim with another prim + if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) + { + //OdePrim op1 = (OdePrim)p1; + //OdePrim op2 = (OdePrim)p2; + //op1.m_collisionscore++; + //op2.m_collisionscore++; + + + //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + //if (contacts[i].depth >= 0.25f) + //{ + // Don't collide, one or both prim will expld. + + + //op1.m_interpenetrationcount++; + //op2.m_interpenetrationcount++; + //interpenetrations_before_disable = 200; + //if (op1.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //} + //if (op2.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + // op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + + //contacts[i].depth = contacts[i].depth / 8f; + //contacts[i].normal = new d.Vector3(0, 0, 1); + //} + //if (op1.m_disabled || op2.m_disabled) + //{ + //Manually disabled objects stay disabled + //contacts[i].depth = 0f; + //} + } + if (contacts[i].depth >= 1.00f) + { + //m_log.Info("[P]: " + contacts[i].depth.ToString()); + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Unknown) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Unknown)) + { + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + OdeCharacter character = (OdeCharacter) p2; + + //p2.CollidingObj = true; + contacts[i].depth = 0.00000003f; + p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f); + contacts[i].pos = + new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), + contacts[i].pos.Y + (p1.Size.Y/2), + contacts[i].pos.Z + (p1.Size.Z/2)); + character.SetPidStatus(true); + } + else + { + } + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + OdeCharacter character = (OdeCharacter)p1; + + //p2.CollidingObj = true; + contacts[i].depth = 0.00000003f; + p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f); + contacts[i].pos = + new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), + contacts[i].pos.Y + (p1.Size.Y/2), + contacts[i].pos.Z + (p1.Size.Z/2)); + character.SetPidStatus(true); + } + else + { + //contacts[i].depth = 0.0000000f; + } + } + } + } + + #endregion + + if (contacts[i].depth >= 0f) + { + // If we're collidng against terrain + if (name1 == "Terrain" || name2 == "Terrain") + { + // If we're moving + if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && + (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the movement terrain contact + AvatarMovementTerrainContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); + } + else + { + // Use the non moving terrain contact + TerrainContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); + } + } + else + { + // we're colliding with prim or avatar + + // check if we're moving + if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && + (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the Movement prim contact + AvatarMovementprimContact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); + } + else + { + // Use the non movement contact + contact.geom = contacts[i]; + joint = d.JointCreateContact(world, contactgroup, ref contact); + } + } + d.JointAttach(joint, b1, b2); + } + + if (count > 3) + { + // If there are more then 3 contact points, it's likely + // that we've got a pile of objects + // + // We don't want to send out hundreds of terse updates over and over again + // so lets throttle them and send them again after it's somewhat sorted out. + p2.ThrottleUpdates = true; + } + //System.Console.WriteLine(count.ToString()); + //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); + } + } + } + private float GetTerrainHeightAtXY(float x, float y) + { + return (float)_origheightmap[(int)y * Constants.RegionSize + (int)x]; + + + } + + /// + /// This is our collision testing routine in ODE + /// + /// + private void collision_optimized(float timeStep) + { + + foreach (OdeCharacter chr in _characters) + { + // Reset the collision values to false + // since we don't know if we're colliding yet + + chr.IsColliding = false; + chr.CollidingGround = false; + chr.CollidingObj = false; + + // test the avatar's geometry for collision with the space + // This will return near and the space that they are the closest to + // And we'll run this again against the avatar and the space segment + // This will return with a bunch of possible objects in the space segment + // and we'll run it again on all of them. + try + { + d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); + //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) + //{ + //chr.Position.Z = terrainheight + 10.0f; + //forcedZ = true; + //} + } + + + // If the sim is running slow this frame, + // don't process collision for prim! + if (timeStep < (m_SkipFramesAtms/3)) + { + foreach (OdePrim chr in _activeprims) + { + // This if may not need to be there.. it might be skipped anyway. + if (d.BodyIsEnabled(chr.Body) && (!chr.m_disabled)) + { + try + { + d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + //calculateSpaceForGeom(chr.Position) + //foreach (OdePrim ch2 in _prims) + /// should be a separate space -- lots of avatars will be N**2 slow + //{ + //if (ch2.IsPhysical && d.BodyIsEnabled(ch2.Body)) + //{ + // Only test prim that are 0.03 meters away in one direction. + // This should be Optimized! + + //if ((Math.Abs(ch2.Position.X - chr.Position.X) < 0.03) || (Math.Abs(ch2.Position.Y - chr.Position.Y) < 0.03) || (Math.Abs(ch2.Position.X - chr.Position.X) < 0.03)) + //{ + //d.SpaceCollide2(chr.prim_geom, ch2.prim_geom, IntPtr.Zero, nearCallback); + //} + //} + //} + } + try + { + d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + } + } + else + { + // Everything is going slow, so we're skipping object to object collisions + // At least collide test against the ground. + foreach (OdePrim chr in _activeprims) + { + // This if may not need to be there.. it might be skipped anyway. + if (d.BodyIsEnabled(chr.Body)) + { + // Collide test the prims with the terrain.. since if you don't do this, + // next frame, all of the physical prim in the scene will awaken and explode upwards + tmpSpace = calculateSpaceForGeom(chr.Position); + if (tmpSpace != (IntPtr) 0 && d.GeomIsSpace(tmpSpace)) + d.SpaceCollide2(calculateSpaceForGeom(chr.Position), chr.prim_geom, IntPtr.Zero, nearCallback); + d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback); + } + } + } + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + PhysicsVector pos = new PhysicsVector(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size); + _characters.Add(newAv); + + return newAv; + } + + public override void RemoveAvatar(PhysicsActor actor) + { + lock (OdeLock) + { + ((OdeCharacter) actor).Destroy(); + _characters.Remove((OdeCharacter) actor); + } + } + + public override void RemovePrim(PhysicsActor prim) + { + if (prim is OdePrim) + { + lock (OdeLock) + { + OdePrim p = (OdePrim) prim; + + p.setPrimForRemoval(); + AddPhysicsActorTaint(prim); + //RemovePrimThreadLocked(p); + } + } + } + + /// + /// This is called from within simulate but outside the locked portion + /// We need to do our own locking here + /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. + /// + /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory + /// that the space was using. + /// + /// + public void RemovePrimThreadLocked(OdePrim prim) + { + lock (ode) + { + if (prim.prim_geom != (IntPtr)0) + { + while (ode.lockquery()) + { + } + ode.dlock(world); + //System.Threading.Thread.Sleep(20); + prim.ResetTaints(); + + + if (prim.IsPhysical) + { + prim.disableBody(); + } + // we don't want to remove the main space + + // If the geometry is in the targetspace, remove it from the target space + //m_log.Warn(prim.m_targetSpace); + + //if (prim.m_targetSpace != (IntPtr)0) + //{ + if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom)) + { + + if (d.GeomIsSpace(prim.m_targetSpace)) + { + waitForSpaceUnlock(prim.m_targetSpace); + d.SpaceRemove(prim.m_targetSpace, prim.prim_geom); + prim.m_targetSpace = (IntPtr) 0; + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + + ((OdePrim)prim).m_targetSpace.ToString()); + } + + } + //} + //m_log.Warn(prim.prim_geom); + try + { + if (prim.prim_geom != (IntPtr)0) + { + d.GeomDestroy(prim.prim_geom); + prim.prim_geom = (IntPtr)0; + } + else + { + m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene"); + } + + } + catch (System.AccessViolationException) + { + m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed."); + } + _prims.Remove(prim); + + //If there are no more geometries in the sub-space, we don't need it in the main space anymore + //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) + //{ + //if (!(prim.m_targetSpace.Equals(null))) + //{ + //if (d.GeomIsSpace(prim.m_targetSpace)) + //{ + //waitForSpaceUnlock(prim.m_targetSpace); + //d.SpaceRemove(space, prim.m_targetSpace); + // free up memory used by the space. + //d.SpaceDestroy(prim.m_targetSpace); + //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position); + //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]); + //} + //else + //{ + //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + + //((OdePrim) prim).m_targetSpace.ToString()); + //} + //} + //} + } + + ode.dunlock(world); + } + } + + /// + /// Takes a space pointer and zeros out the array we're using to hold the spaces + /// + /// + public void resetSpaceArrayItemToZero(IntPtr space) + { + for (int x = 0; x < staticPrimspace.GetLength(0); x++) + { + for (int y = 0; y < staticPrimspace.GetLength(1); y++) + { + if (staticPrimspace[x, y] == space) + staticPrimspace[x, y] = IntPtr.Zero; + } + } + } + + public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY) + { + staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; + } + + /// + /// Called when a static prim moves. Allocates a space for the prim based on it's position + /// + /// the pointer to the geom that moved + /// the position that the geom moved to + /// a pointer to the space it was in before it was moved. + /// a pointer to the new space it's in + public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos, IntPtr currentspace) + { + + // Called from setting the Position and Size of an ODEPrim so + // it's already in locked space. + + // we don't want to remove the main space + // we don't need to test physical here because this function should + // never be called if the prim is physical(active) + + // All physical prim end up in the root space + System.Threading.Thread.Sleep(20); + if (currentspace != space) + { + if (d.SpaceQuery(currentspace, geom) && currentspace != (IntPtr) 0) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + d.SpaceRemove(currentspace, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace.ToString() + + " Geom:" + geom.ToString()); + } + } + else + { + IntPtr sGeomIsIn = d.GeomGetSpace(geom); + if (!(sGeomIsIn.Equals(null))) + { + if (sGeomIsIn != (IntPtr) 0) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(sGeomIsIn); + d.SpaceRemove(sGeomIsIn, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + sGeomIsIn.ToString() + " Geom:" + geom.ToString()); + } + } + } + } + + //If there are no more geometries in the sub-space, we don't need it in the main space anymore + if (d.SpaceGetNumGeoms(currentspace) == 0) + { + if (currentspace != (IntPtr) 0) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + waitForSpaceUnlock(space); + d.SpaceRemove(space, currentspace); + // free up memory used by the space. + + d.SpaceDestroy(currentspace); + resetSpaceArrayItemToZero(currentspace); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + currentspace.ToString() + " Geom:" + geom.ToString()); + } + } + } + } + else + { + // this is a physical object that got disabled. ;.; + if (currentspace != (IntPtr)0 && geom != (IntPtr)0) + { + if (d.SpaceQuery(currentspace, geom)) + { + + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + d.SpaceRemove(currentspace, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + currentspace.ToString() + " Geom:" + geom.ToString()); + } + } + else + { + IntPtr sGeomIsIn = d.GeomGetSpace(geom); + if (!(sGeomIsIn.Equals(null))) + { + if (sGeomIsIn != (IntPtr)0) + { + if (d.GeomIsSpace(sGeomIsIn)) + { + waitForSpaceUnlock(sGeomIsIn); + d.SpaceRemove(sGeomIsIn, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + sGeomIsIn.ToString() + " Geom:" + geom.ToString()); + } + } + } + } + } + } + + // The routines in the Position and Size sections do the 'inserting' into the space, + // so all we have to do is make sure that the space that we're putting the prim into + // is in the 'main' space. + int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos); + IntPtr newspace = calculateSpaceForGeom(pos); + + if (newspace == IntPtr.Zero) + { + newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); + d.HashSpaceSetLevels(newspace, -4, 66); + } + + return newspace; + } + + /// + /// Creates a new space at X Y + /// + /// + /// + /// A pointer to the created space + public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) + { + // creating a new space for prim and inserting it into main space. + staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); + waitForSpaceUnlock(space); + d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); + return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; + } + + /// + /// Calculates the space the prim should be in by it's position + /// + /// + /// a pointer to the space. This could be a new space or reused space. + public IntPtr calculateSpaceForGeom(PhysicsVector pos) + { + IntPtr locationbasedspace =IntPtr.Zero; + + int[] xyspace = calculateSpaceArrayItemFromPos(pos); + //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString()); + locationbasedspace = staticPrimspace[xyspace[0], xyspace[1]]; + + //locationbasedspace = space; + return locationbasedspace; + } + + /// + /// Holds the space allocation logic + /// + /// + /// an array item based on the position + public int[] calculateSpaceArrayItemFromPos(PhysicsVector pos) + { + int[] returnint = new int[2]; + + returnint[0] = (int) (pos.X/metersInSpace); + + if (returnint[0] > ((int) (259f/metersInSpace))) + returnint[0] = ((int) (259f/metersInSpace)); + if (returnint[0] < 0) + returnint[0] = 0; + + returnint[1] = (int) (pos.Y/metersInSpace); + if (returnint[1] > ((int) (259f/metersInSpace))) + returnint[1] = ((int) (259f/metersInSpace)); + if (returnint[1] < 0) + returnint[1] = 0; + + + return returnint; + } + + private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, + IMesh mesh, PrimitiveBaseShape pbs, bool isphysical, uint localID) // rex, localid + { + PhysicsVector pos = new PhysicsVector(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + PhysicsVector siz = new PhysicsVector(); + siz.X = size.X; + siz.Y = size.Y; + siz.Z = size.Z; + Quaternion rot = new Quaternion(); + rot.w = rotation.w; + rot.x = rotation.x; + rot.y = rotation.y; + rot.z = rotation.z; + + + + OdePrim newPrim; + lock (OdeLock) + { + newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); + + _prims.Add(newPrim); + } + + + return newPrim; + } + + public void addActivePrim(OdePrim activatePrim) + { + // adds active prim.. (ones that should be iterated over in collisions_optimized + + _activeprims.Add(activatePrim); + } + + public void remActivePrim(OdePrim deactivatePrim) + { + _activeprims.Remove(deactivatePrim); + } + + public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) + { +/* String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + + m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); +*/ + return 1; + } + + public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) + { + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + +// m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); + + d.Vector3 v0 = new d.Vector3(); + d.Vector3 v1 = new d.Vector3(); + d.Vector3 v2 = new d.Vector3(); + + d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); +// m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); + + return 1; + } + + /// + /// Routine to figure out if we need to mesh this prim with our mesher + /// + /// + /// + public bool needsMeshing(PrimitiveBaseShape pbs) + { + if (pbs.ProfileHollow != 0) + return true; + + if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) + return true; + + if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) + return true; + + if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) + return true; + + if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + return true; + + if (pbs.ProfileShape == ProfileShape.EquilateralTriangle) + return true; + + return false; + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, uint localID) //To be removed rex, localid + { + return AddPrimShape(primName, pbs, position, size, rotation, false,localID); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) // rex, localid + { + PhysicsActor result; + IMesh mesh = null; + + switch (pbs.ProfileShape) + { + case ProfileShape.Square: + /// support simple box & hollow box now; later, more shapes + if (needsMeshing(pbs)) + { + mesh = mesher.CreateMesh(primName, pbs, size); + } + + break; + } + + result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, localID); // rex, localid + + + return result; + } + + /// + /// Called after our prim properties are set Scale, position etc. + /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex + /// This assures us that we have no race conditions + /// + /// + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + if (prim is OdePrim) + { + OdePrim taintedprim = ((OdePrim) prim); + if (!(_taintedPrim.Contains(taintedprim))) + _taintedPrim.Add(taintedprim); + } + } + + /// + /// This is our main simulate loop + /// It's thread locked by a Mutex in the scene. + /// It holds Collisions, it instructs ODE to step through the physical reactions + /// It moves the objects around in memory + /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) + /// + /// + /// + public override float Simulate(float timeStep) + { + float fps = 0; + + step_time += timeStep; + + + // If We're loaded down by something else, + // or debugging with the Visual Studio project on pause + // skip a few frames to catch up gracefully. + // without shooting the physicsactors all over the place + + + if (step_time >= m_SkipFramesAtms) + { + // Instead of trying to catch up, it'll do 5 physics frames only + step_time = ODE_STEPSIZE; + m_physicsiterations = 5; + } + else + { + m_physicsiterations = 10; + } + lock (OdeLock) + { + // Process 10 frames if the sim is running normal.. + // process 5 frames if the sim is running slow + try + { + d.WorldSetQuickStepNumIterations(world, m_physicsiterations); + } + catch (StackOverflowException) + { + m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); + ode.drelease(world); + base.TriggerPhysicsBasedRestart(); + } + + int i = 0; + + // Figure out the Frames Per Second we're going at. + //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size + fps = (step_time/ODE_STEPSIZE) * 1000; + + while (step_time > 0.0f) + { + lock (ode) + { + if (!ode.lockquery()) + { + ode.dlock(world); + try + { + foreach (OdeCharacter actor in _characters) + { + if (actor != null) + actor.Move(timeStep); + } + + collision_optimized(timeStep); + + d.WorldQuickStep(world, ODE_STEPSIZE); + + d.JointGroupEmpty(contactgroup); + ode.dunlock(world); + } + catch (Exception e) + { + m_log.Error("[PHYSICS]: " + e.Message.ToString() + e.TargetSite.ToString()); + ode.dunlock(world); + } + + step_time -= ODE_STEPSIZE; + i++; + } + else + { + fps = 0; + } + } + } + + foreach (OdeCharacter actor in _characters) + { + if (actor != null) + actor.UpdatePositionAndVelocity(); + } + + if (!ode.lockquery()) + { + bool processedtaints = false; + foreach (OdePrim prim in _taintedPrim) + { + if (prim.m_taintremove) + { + RemovePrimThreadLocked(prim); + } + + prim.ProcessTaints(timeStep); + + processedtaints = true; + prim.m_collisionscore = 0; + } + if (processedtaints) + _taintedPrim = new List(); + } + foreach (OdePrim prim in _activeprims) + { + prim.m_collisionscore = 0; + } + + + + if (timeStep < 0.2f) + { + foreach (OdePrim actor in _activeprims) + { + if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) + { + actor.UpdatePositionAndVelocity(); + } + } + } + } + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + // for now we won't be multithreaded + get { return (false); } + } + public float[] ResizeTerrain512NearestNeighbour(float[] heightMap) + { + float[] returnarr = new float[262144]; + float[,] resultarr = new float[m_regionWidth, m_regionHeight]; + + // Filling out the array into it's multi-dimentional components + for (int y = 0; y < m_regionHeight; y++) + { + for (int x = 0; x < m_regionWidth; x++) + { + resultarr[y, x] = heightMap[y * m_regionWidth + x]; + } + } + + // Resize using Nearest Neighbour + + // This particular way is quick but it only works on a multiple of the original + + // The idea behind this method can be described with the following diagrams + // second pass and third pass happen in the same loop really.. just separated + // them to show what this does. + + // First Pass + // ResultArr: + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + + // Second Pass + // ResultArr2: + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + + // Third pass fills in the blanks + // ResultArr2: + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + + // X,Y = . + // X+1,y = ^ + // X,Y+1 = * + // X+1,Y+1 = # + + // Filling in like this; + // .* + // ^# + // 1st . + // 2nd * + // 3rd ^ + // 4th # + // on single loop. + + float[,] resultarr2 = new float[512, 512]; + for (int y = 0; y < m_regionHeight; y++) + { + for (int x = 0; x < m_regionWidth; x++) + { + resultarr2[y * 2, x * 2] = resultarr[y, x]; + + if (y < m_regionHeight) + { + resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x]; + } + if (x < m_regionWidth) + { + resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x]; + } + if (x < m_regionWidth && y < m_regionHeight) + { + resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x]; + } + } + } + + //Flatten out the array + int i = 0; + for (int y = 0; y < 512; y++) + { + for (int x = 0; x < 512; x++) + { + if (resultarr2[y, x] <= 0) + returnarr[i] = 0.0000001f; + else + returnarr[i] = resultarr2[y, x]; + + i++; + } + } + + return returnarr; + } + public float[] ResizeTerrain512Interpolation(float[] heightMap) + { + float[] returnarr = new float[262144]; + float[,] resultarr = new float[m_regionWidth,m_regionHeight]; + + // Filling out the array into it's multi-dimentional components + for (int y = 0; y < m_regionHeight; y++) + { + for (int x = 0; x < m_regionWidth; x++) + { + resultarr[y, x] = heightMap[y*m_regionWidth + x]; + } + } + + // Resize using interpolation + + // This particular way is quick but it only works on a multiple of the original + + // The idea behind this method can be described with the following diagrams + // second pass and third pass happen in the same loop really.. just separated + // them to show what this does. + + // First Pass + // ResultArr: + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + + // Second Pass + // ResultArr2: + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + + // Third pass fills in the blanks + // ResultArr2: + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + + // X,Y = . + // X+1,y = ^ + // X,Y+1 = * + // X+1,Y+1 = # + + // Filling in like this; + // .* + // ^# + // 1st . + // 2nd * + // 3rd ^ + // 4th # + // on single loop. + + float[,] resultarr2 = new float[512,512]; + for (int y = 0; y < m_regionHeight; y++) + { + for (int x = 0; x < m_regionWidth; x++) + { + resultarr2[y*2, x*2] = resultarr[y, x]; + + if (y < m_regionHeight) + { + if (y + 1 < m_regionHeight) + { + if (x + 1 < m_regionWidth) + { + resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2); + } + } + else + { + resultarr2[(y*2) + 1, x*2] = resultarr[y, x]; + } + } + if (x < m_regionWidth) + { + if (x + 1 < m_regionWidth) + { + if (y + 1 < m_regionHeight) + { + resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2); + } + } + else + { + resultarr2[y*2, (x*2) + 1] = resultarr[y, x]; + } + } + if (x < m_regionWidth && y < m_regionHeight) + { + if ((x + 1 < m_regionWidth) && (y + 1 < m_regionHeight)) + { + resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x]; + } + } + } + } + //Flatten out the array + int i = 0; + for (int y = 0; y < 512; y++) + { + for (int x = 0; x < 512; x++) + { + if (resultarr2[y, x] <= 0) + returnarr[i] = 0.0000001f; + else + returnarr[i] = resultarr2[y, x]; + + i++; + } + } + + return returnarr; + } + + public override void SetTerrain(float[] heightMap) + { + // this._heightmap[i] = (double)heightMap[i]; + // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) + // also, creating a buffer zone of one extra sample all around + _origheightmap = heightMap; + const uint heightmapWidth = m_regionWidth + 2; + const uint heightmapHeight = m_regionHeight + 2; + const uint heightmapWidthSamples = 2*m_regionWidth + 2; + const uint heightmapHeightSamples = 2*m_regionHeight + 2; + const float scale = 1.0f; + const float offset = 0.0f; + const float thickness = 0.2f; + const int wrap = 0; + + //Double resolution + heightMap = ResizeTerrain512Interpolation(heightMap); + for (int x = 0; x < heightmapWidthSamples; x++) + { + for (int y = 0; y < heightmapHeightSamples; y++) + { + int xx = Util.Clip(x - 1, 0, 511); + int yy = Util.Clip(y - 1, 0, 511); + + float val = heightMap[yy*512 + xx]; + _heightmap[x*heightmapHeightSamples + y] = val; + } + } + + lock (OdeLock) + { + if (!(LandGeom == (IntPtr) 0)) + { + d.SpaceRemove(space, LandGeom); + } + IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); + d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth, heightmapHeight, + (int) heightmapWidthSamples, (int) heightmapHeightSamples, scale, + offset, thickness, wrap); + d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); + LandGeom = d.CreateHeightfield(space, HeightmapData, 1); + geom_name_map[LandGeom] = "Terrain"; + + d.Matrix3 R = new d.Matrix3(); + + Quaternion q1 = Quaternion.FromAngleAxis(1.5707f, new Vector3(1, 0, 0)); + Quaternion q2 = Quaternion.FromAngleAxis(1.5707f, new Vector3(0, 1, 0)); + //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); + + q1 = q1*q2; + //q1 = q1 * q3; + Vector3 v3 = new Vector3(); + float angle = 0; + q1.ToAngleAxis(ref angle, ref v3); + + d.RFromAxisAndAngle(out R, v3.x, v3.y, v3.z, angle); + d.GeomSetRotation(LandGeom, ref R); + d.GeomSetPosition(LandGeom, 128, 128, 0); + } + } + + public override void DeleteTerrain() + { + } + + public override void Dispose() + { + lock (OdeLock) + { + + foreach (OdePrim prm in _prims) + { + RemovePrim(prm); + } + + foreach (OdeCharacter act in _characters) + { + RemoveAvatar(act); + } + d.WorldDestroy(world); + //d.CloseODE(); + } + } + } +} diff --git a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs index ec84473134..f521cf9980 100644 --- a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs @@ -55,4 +55,4 @@ using System.Runtime.InteropServices; // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): -[assembly : AssemblyVersion("1.0.*")] \ No newline at end of file +[assembly : AssemblyVersion("1.0.*")] diff --git a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs index d772f8dbbd..d38ded6f7c 100644 --- a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs +++ b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs @@ -1,604 +1,663 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -using System; -using System.Collections.Generic; -using Axiom.Math; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.POSPlugin -{ - /// - /// for now will be a very POS physics engine - /// - public class POSPlugin : IPhysicsPlugin - { - public POSPlugin() - { - } - - public bool Init() - { - return true; - } - - public PhysicsScene GetScene() - { - return new POSScene(); - } - - public string GetName() - { - return ("POS"); - } - - public void Dispose() - { - } - } - - public class POSScene : PhysicsScene - { - private List _characters = new List(); - private List _prims = new List(); - private float[] _heightMap; - private const float gravity = -9.8f; - - public POSScene() - { - } - - public override void Initialise(IMesher meshmerizer) - { - // Does nothing right now - } - - public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID) - { - POSCharacter act = new POSCharacter(); - act.Position = position; - _characters.Add(act); - return act; - } - - public override void RemovePrim(PhysicsActor prim) - { - POSPrim p = (POSPrim) prim; - if (_prims.Contains(p)) - { - _prims.Remove(p); - } - } - - public override void RemoveAvatar(PhysicsActor character) - { - POSCharacter act = (POSCharacter) character; - if (_characters.Contains(act)) - { - _characters.Remove(act); - } - } - -/* - public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) - { - return null; - } -*/ - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, uint localID) - { - return AddPrimShape(primName, pbs, position, size, rotation, false,localID); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) - { - POSPrim prim = new POSPrim(); - prim.Position = position; - prim.Orientation = rotation; - prim.Size = size; - _prims.Add(prim); - return prim; - } - - private bool check_collision(POSCharacter c, POSPrim p) - { - /* - Console.WriteLine("checking whether " + c + " collides with " + p + - " absX: " + Math.Abs(p.Position.X - c.Position.X) + - " sizeX: " + p.Size.X * 0.5 + 0.5); - */ - - Vector3 rotatedPos = p.Orientation.Inverse()* - new Vector3(c.Position.X - p.Position.X, c.Position.Y - p.Position.Y, - c.Position.Z - p.Position.Z); - Vector3 avatarSize = p.Orientation.Inverse()*new Vector3(c.Size.X, c.Size.Y, c.Size.Z); - - if (Math.Abs(rotatedPos.x) >= (p.Size.X*0.5 + Math.Abs(avatarSize.x))) - { - return false; - } - if (Math.Abs(rotatedPos.y) >= (p.Size.Y*0.5 + Math.Abs(avatarSize.y))) - { - return false; - } - if (Math.Abs(rotatedPos.z) >= (p.Size.Z*0.5 + Math.Abs(avatarSize.z))) - { - return false; - } - return true; - } - - private bool check_all_prims(POSCharacter c) - { - for (int i = 0; i < _prims.Count; ++i) - { - if (check_collision(c, _prims[i])) - return true; - } - return false; - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - float fps = 0; - for (int i = 0; i < _characters.Count; ++i) - { - fps++; - POSCharacter character = _characters[i]; - - float oldposX = character.Position.X; - float oldposY = character.Position.Y; - float oldposZ = character.Position.Z; - - if (!character.Flying) - { - character._target_velocity.Z += gravity*timeStep; - } - - bool forcedZ = false; - character.Position.X += character._target_velocity.X*timeStep; - character.Position.Y += character._target_velocity.Y*timeStep; - - if (character.Position.Y < 0) - { - character.Position.Y = 0.1F; - } - else if (character.Position.Y >= 256) - { - character.Position.Y = 255.9F; - } - - if (character.Position.X < 0) - { - character.Position.X = 0.1F; - } - else if (character.Position.X >= 256) - { - character.Position.X = 255.9F; - } - - float terrainheight = _heightMap[(int) character.Position.Y*256 + (int) character.Position.X]; - if (character.Position.Z + (character._target_velocity.Z*timeStep) < terrainheight + 2) - { - character.Position.Z = terrainheight + 1.0f; - forcedZ = true; - } - else - { - character.Position.Z += character._target_velocity.Z*timeStep; - } - - /// this is it -- the magic you've all been waiting for! Ladies and gentlemen -- - /// Completely Bogus Collision Detection!!! - /// better known as the CBCD algorithm - - if (check_all_prims(character)) - { - character.Position.Z = oldposZ; // first try Z axis - if (check_all_prims(character)) - { - character.Position.Z = oldposZ + 0.4f; // try harder - if (check_all_prims(character)) - { - character.Position.X = oldposX; - character.Position.Y = oldposY; - character.Position.Z = oldposZ; - character.Position.X = character.Position.X + (character._target_velocity.X*timeStep); - if (check_all_prims(character)) - { - character.Position.X = oldposX; - } - character.Position.Y = character.Position.Y + (character._target_velocity.Y*timeStep); - if (check_all_prims(character)) - { - character.Position.Y = oldposY; - } - } - else - { - forcedZ = true; - } - } - else - { - forcedZ = true; - } - } - - if (character.Position.Y < 0) - { - character.Position.Y = 0.1F; - } - else if (character.Position.Y >= 256) - { - character.Position.Y = 255.9F; - } - - if (character.Position.X < 0) - { - character.Position.X = 0.1F; - } - else if (character.Position.X >= 256) - { - character.Position.X = 255.9F; - } - - character._velocity.X = (character.Position.X - oldposX)/timeStep; - character._velocity.Y = (character.Position.Y - oldposY)/timeStep; - - if (forcedZ) - { - character._velocity.Z = 0; - character._target_velocity.Z = 0; - character.RequestPhysicsterseUpdate(); - } - else - { - character._velocity.Z = (character.Position.Z - oldposZ)/timeStep; - } - } - return fps; - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - get { return (false); // for now we won't be multithreaded - } - } - - public override void SetTerrain(float[] heightMap) - { - _heightMap = heightMap; - } - - public override void DeleteTerrain() - { - } - } - - public class POSCharacter : PhysicsActor - { - private PhysicsVector _position; - public PhysicsVector _velocity; - public PhysicsVector _target_velocity = PhysicsVector.Zero; - private PhysicsVector _acceleration; - private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; - private bool flying; - private bool iscolliding; - - public POSCharacter() - { - _velocity = new PhysicsVector(); - _position = new PhysicsVector(); - _acceleration = new PhysicsVector(); - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override PhysicsVector RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool Flying - { - get { return flying; } - set { flying = value; } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override PhysicsVector Position - { - get { return _position; } - set { _position = value; } - } - - public override PhysicsVector Size - { - get { return new PhysicsVector(0.5f, 0.5f, 1.0f); } - set { } - } - - public override float Mass - { - get { return 0f; } - } - - public override PhysicsVector Force - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override PhysicsVector Velocity - { - get { return _velocity; } - set { _target_velocity = value; } - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - public override bool Kinematic - { - get { return true; } - set { } - } - - public void SetAcceleration(PhysicsVector accel) - { - _acceleration = accel; - } - - public override void AddForce(PhysicsVector force) - { - } - - public override void SetMomentum(PhysicsVector momentum) - { - } - } - - public class POSPrim : PhysicsActor - { - private PhysicsVector _position; - private PhysicsVector _velocity; - private PhysicsVector _acceleration; - private PhysicsVector _size; - private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; - private Quaternion _orientation; - private bool iscolliding; - - public POSPrim() - { - _velocity = new PhysicsVector(); - _position = new PhysicsVector(); - _acceleration = new PhysicsVector(); - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Prim; } - set { return; } - } - - public override PhysicsVector RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override PhysicsVector Position - { - get { return _position; } - set { _position = value; } - } - - public override PhysicsVector Size - { - get { return _size; } - set { _size = value; } - } - - public override float Mass - { - get { return 0f; } - } - - public override PhysicsVector Force - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override PhysicsVector Velocity - { - get { return _velocity; } - set { _velocity = value; } - } - - public override Quaternion Orientation - { - get { return _orientation; } - set { _orientation = value; } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - public override bool Kinematic - { - get { return true; } - set { } - } - - public void SetAcceleration(PhysicsVector accel) - { - _acceleration = accel; - } - - public override void AddForce(PhysicsVector force) - { - } - - public override void SetMomentum(PhysicsVector momentum) - { - } - - public override bool Flying - { - get { return false; } - set { } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using System.Collections.Generic; +using Axiom.Math; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.POSPlugin +{ + /// + /// for now will be a very POS physics engine + /// + public class POSPlugin : IPhysicsPlugin + { + public POSPlugin() + { + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + return new POSScene(); + } + + public string GetName() + { + return ("POS"); + } + + public void Dispose() + { + } + } + + public class POSScene : PhysicsScene + { + private List _characters = new List(); + private List _prims = new List(); + private float[] _heightMap; + private const float gravity = -9.8f; + + public POSScene() + { + } + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + public override void Dispose() + { + + } + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + POSCharacter act = new POSCharacter(); + act.Position = position; + _characters.Add(act); + return act; + } + + public override void RemovePrim(PhysicsActor prim) + { + POSPrim p = (POSPrim) prim; + if (_prims.Contains(p)) + { + _prims.Remove(p); + } + } + + public override void RemoveAvatar(PhysicsActor character) + { + POSCharacter act = (POSCharacter) character; + if (_characters.Contains(act)) + { + _characters.Remove(act); + } + } + +/* + public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation) + { + return null; + } +*/ + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, uint localID) + { + return AddPrimShape(primName, pbs, position, size, rotation, false,localID); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) + { + POSPrim prim = new POSPrim(); + prim.Position = position; + prim.Orientation = rotation; + prim.Size = size; + _prims.Add(prim); + return prim; + } + + private bool check_collision(POSCharacter c, POSPrim p) + { + /* + Console.WriteLine("checking whether " + c + " collides with " + p + + " absX: " + Math.Abs(p.Position.X - c.Position.X) + + " sizeX: " + p.Size.X * 0.5 + 0.5); + */ + + Vector3 rotatedPos = p.Orientation.Inverse()* + new Vector3(c.Position.X - p.Position.X, c.Position.Y - p.Position.Y, + c.Position.Z - p.Position.Z); + Vector3 avatarSize = p.Orientation.Inverse()*new Vector3(c.Size.X, c.Size.Y, c.Size.Z); + + if (Math.Abs(rotatedPos.x) >= (p.Size.X*0.5 + Math.Abs(avatarSize.x))) + { + return false; + } + if (Math.Abs(rotatedPos.y) >= (p.Size.Y*0.5 + Math.Abs(avatarSize.y))) + { + return false; + } + if (Math.Abs(rotatedPos.z) >= (p.Size.Z*0.5 + Math.Abs(avatarSize.z))) + { + return false; + } + return true; + } + + private bool check_all_prims(POSCharacter c) + { + for (int i = 0; i < _prims.Count; ++i) + { + if (check_collision(c, _prims[i])) + { + + return true; + } + + } + + return false; + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + float fps = 0; + for (int i = 0; i < _characters.Count; ++i) + { + fps++; + POSCharacter character = _characters[i]; + + float oldposX = character.Position.X; + float oldposY = character.Position.Y; + float oldposZ = character.Position.Z; + + if (!character.Flying) + { + character._target_velocity.Z += gravity*timeStep; + } + + bool forcedZ = false; + character.Position.X += character._target_velocity.X*timeStep; + character.Position.Y += character._target_velocity.Y*timeStep; + + if (character.Position.Y < 0) + { + character.Position.Y = 0.1F; + } + else if (character.Position.Y >= Constants.RegionSize) + { + character.Position.Y = Constants.RegionSize - 0.1f; + } + + if (character.Position.X < 0) + { + character.Position.X = 0.1F; + } + else if (character.Position.X >= Constants.RegionSize) + { + character.Position.X = Constants.RegionSize - 0.1f; + } + + float terrainheight = _heightMap[(int)character.Position.Y * Constants.RegionSize + (int)character.Position.X]; + if (character.Position.Z + (character._target_velocity.Z*timeStep) < terrainheight + 2) + { + character.Position.Z = terrainheight + 1.0f; + forcedZ = true; + } + else + { + character.Position.Z += character._target_velocity.Z*timeStep; + } + + /// this is it -- the magic you've all been waiting for! Ladies and gentlemen -- + /// Completely Bogus Collision Detection!!! + /// better known as the CBCD algorithm + + if (check_all_prims(character)) + { + character.Position.Z = oldposZ; // first try Z axis + if (check_all_prims(character)) + { + character.Position.Z = oldposZ + 0.4f; // try harder + if (check_all_prims(character)) + { + character.Position.X = oldposX; + character.Position.Y = oldposY; + character.Position.Z = oldposZ; + character.Position.X = character.Position.X + (character._target_velocity.X*timeStep); + if (check_all_prims(character)) + { + character.Position.X = oldposX; + } + character.Position.Y = character.Position.Y + (character._target_velocity.Y*timeStep); + if (check_all_prims(character)) + { + character.Position.Y = oldposY; + } + } + else + { + forcedZ = true; + } + } + else + { + forcedZ = true; + } + } + + if (character.Position.Y < 0) + { + character.Position.Y = 0.1F; + } + else if (character.Position.Y >= Constants.RegionSize) + { + character.Position.Y = Constants.RegionSize - 0.1f; + } + + if (character.Position.X < 0) + { + character.Position.X = 0.1F; + } + else if (character.Position.X >= Constants.RegionSize) + { + character.Position.X = Constants.RegionSize - 0.1f; + } + + character._velocity.X = (character.Position.X - oldposX)/timeStep; + character._velocity.Y = (character.Position.Y - oldposY)/timeStep; + + if (forcedZ) + { + character._velocity.Z = 0; + character._target_velocity.Z = 0; + ((PhysicsActor)character).IsColliding = true; + character.RequestPhysicsterseUpdate(); + } + else + { + ((PhysicsActor)character).IsColliding = false; + character._velocity.Z = (character.Position.Z - oldposZ)/timeStep; + } + } + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + get { return (false); // for now we won't be multithreaded + } + } + + public override void SetTerrain(float[] heightMap) + { + _heightMap = heightMap; + } + + public override void DeleteTerrain() + { + } + } + + public class POSCharacter : PhysicsActor + { + private PhysicsVector _position; + public PhysicsVector _velocity; + public PhysicsVector _target_velocity = PhysicsVector.Zero; + private PhysicsVector _acceleration; + private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + private bool flying; + private bool iscolliding; + + public POSCharacter() + { + _velocity = new PhysicsVector(); + _position = new PhysicsVector(); + _acceleration = new PhysicsVector(); + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get { return _position; } + set { _position = value; } + } + + public override PhysicsVector Size + { + get { return new PhysicsVector(0.5f, 0.5f, 1.0f); } + set { } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _target_velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public override bool Kinematic + { + get { return true; } + set { } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + public override void CrossingFailure() + { + + } + } + + public class POSPrim : PhysicsActor + { + private PhysicsVector _position; + private PhysicsVector _velocity; + private PhysicsVector _acceleration; + private PhysicsVector _size; + private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + private Quaternion _orientation; + private bool iscolliding; + + public POSPrim() + { + _velocity = new PhysicsVector(); + _position = new PhysicsVector(); + _acceleration = new PhysicsVector(); + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Prim; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get { return _position; } + set { _position = value; } + } + + public override PhysicsVector Size + { + get { return _size; } + set { _size = value; } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override Quaternion Orientation + { + get { return _orientation; } + set { _orientation = value; } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public override bool Kinematic + { + get { return true; } + set { } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + public override bool Flying + { + get { return false; } + set { } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + public override void CrossingFailure() + { + + } + + } +} diff --git a/OpenSim/Region/Physics/PhysXPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/PhysXPlugin/AssemblyInfo.cs index dc4427061b..7ae94c1e9f 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/AssemblyInfo.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/AssemblyInfo.cs @@ -55,4 +55,4 @@ using System.Runtime.InteropServices; // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): -[assembly : AssemblyVersion("1.0.*")] \ No newline at end of file +[assembly : AssemblyVersion("1.0.*")] diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs index dbb3281f14..8853d0da3f 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs @@ -1,548 +1,599 @@ -/*/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -using System; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using PhysXWrapper; -using Quaternion=Axiom.Math.Quaternion; - -namespace OpenSim.Region.Physics.PhysXPlugin -{ - /// - /// Will be the PhysX plugin but for now will be a very basic physics engine - /// - public class PhysXPlugin : IPhysicsPlugin - { - private PhysXScene _mScene; - - public PhysXPlugin() - { - } - - public bool Init() - { - return true; - } - - public PhysicsScene GetScene() - { - if (_mScene == null) - { - _mScene = new PhysXScene(); - } - return (_mScene); - } - - public string GetName() - { - return ("RealPhysX"); - } - - public void Dispose() - { - } - } - - public class PhysXScene : PhysicsScene - { - private List _characters = new List(); - private List _prims = new List(); - private float[] _heightMap = null; - private NxPhysicsSDK mySdk; - private NxScene scene; - - public PhysXScene() - { - mySdk = NxPhysicsSDK.CreateSDK(); - Console.WriteLine("Sdk created - now creating scene"); - scene = mySdk.CreateScene(); - } - - public override void Initialise(IMesher meshmerizer) - { - // Does nothing right now - } - - - public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID) - { - Vec3 pos = new Vec3(); - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z; - PhysXCharacter act = new PhysXCharacter(scene.AddCharacter(pos)); - act.Position = position; - _characters.Add(act); - return act; - } - - public override void RemovePrim(PhysicsActor prim) - { - } - - public override void RemoveAvatar(PhysicsActor actor) - { - } - - private PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation, uint localID) - { - Vec3 pos = new Vec3(); - pos.X = position.X; - pos.Y = position.Y; - pos.Z = position.Z; - Vec3 siz = new Vec3(); - siz.X = size.X; - siz.Y = size.Y; - siz.Z = size.Z; - PhysXPrim act = new PhysXPrim(scene.AddNewBox(pos, siz)); - _prims.Add(act); - return act; - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, uint localID) //To be removed - { - return AddPrimShape(primName, pbs, position, size, rotation, false,localID); - } - - public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, - PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) - { - return AddPrim(position, size, rotation,localID); - } - - public override void AddPhysicsActorTaint(PhysicsActor prim) - { - } - - public override float Simulate(float timeStep) - { - float fps = 0f; - try - { - foreach (PhysXCharacter actor in _characters) - { - actor.Move(timeStep); - } - scene.Simulate(timeStep); - scene.FetchResults(); - scene.UpdateControllers(); - - foreach (PhysXCharacter actor in _characters) - { - actor.UpdatePosition(); - } - } - catch (Exception e) - { - Console.WriteLine(e.Message); - } - return fps; - } - - public override void GetResults() - { - } - - public override bool IsThreaded - { - get { return (false); // for now we won't be multithreaded - } - } - - public override void SetTerrain(float[] heightMap) - { - if (_heightMap != null) - { - Console.WriteLine("PhysX - deleting old terrain"); - scene.DeleteTerrain(); - } - _heightMap = heightMap; - scene.AddTerrain(heightMap); - } - - public override void DeleteTerrain() - { - scene.DeleteTerrain(); - } - } - - public class PhysXCharacter : PhysicsActor - { - private PhysicsVector _position; - private PhysicsVector _velocity; - private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; - private PhysicsVector _acceleration; - private NxCharacter _character; - private bool flying; - private bool iscolliding = false; - private float gravityAccel; - - public PhysXCharacter(NxCharacter character) - { - _velocity = new PhysicsVector(); - _position = new PhysicsVector(); - _acceleration = new PhysicsVector(); - _character = character; - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Agent; } - set { return; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override bool Flying - { - get { return flying; } - set { flying = value; } - } - - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override PhysicsVector RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override PhysicsVector Position - { - get { return _position; } - set - { - _position = value; - Vec3 ps = new Vec3(); - ps.X = value.X; - ps.Y = value.Y; - ps.Z = value.Z; - _character.Position = ps; - } - } - - public override PhysicsVector Size - { - get { return PhysicsVector.Zero; } - set { } - } - - public override float Mass - { - get { return 0f; } - } - - public override PhysicsVector Force - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector Velocity - { - get { return _velocity; } - set { _velocity = value; } - } - - public override bool Kinematic - { - get { return false; } - set { } - } - - public override Quaternion Orientation - { - get { return Quaternion.Identity; } - set { } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - public void SetAcceleration(PhysicsVector accel) - { - _acceleration = accel; - } - - public override void AddForce(PhysicsVector force) - { - } - - public override void SetMomentum(PhysicsVector momentum) - { - } - - public void Move(float timeStep) - { - Vec3 vec = new Vec3(); - vec.X = _velocity.X*timeStep; - vec.Y = _velocity.Y*timeStep; - if (flying) - { - vec.Z = (_velocity.Z)*timeStep; - } - else - { - gravityAccel += -9.8f; - vec.Z = (gravityAccel + _velocity.Z)*timeStep; - } - int res = _character.Move(vec); - if (res == 1) - { - gravityAccel = 0; - } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public void UpdatePosition() - { - Vec3 vec = _character.Position; - _position.X = vec.X; - _position.Y = vec.Y; - _position.Z = vec.Z; - } - } - - - public class PhysXPrim : PhysicsActor - { - private PhysicsVector _velocity; - private PhysicsVector _acceleration; - private PhysicsVector m_rotationalVelocity; - private NxActor _prim; - - public PhysXPrim(NxActor prim) - { - _velocity = new PhysicsVector(); - _acceleration = new PhysicsVector(); - _prim = prim; - } - - public override int PhysicsActorType - { - get { return (int) ActorTypes.Prim; } - set { return; } - } - - public override bool IsPhysical - { - get { return false; } - set { return; } - } - - public override bool SetAlwaysRun - { - get { return false; } - set { return; } - } - - public override bool ThrottleUpdates - { - get { return false; } - set { return; } - } - - public override PhysicsVector RotationalVelocity - { - get { return m_rotationalVelocity; } - set { m_rotationalVelocity = value; } - } - - public override bool Flying - { - get { return false; //no flying prims for you - } - set { } - } - - public override bool IsColliding - { - get { return false; } - set { } - } - - public override bool CollidingGround - { - get { return false; } - set { return; } - } - - public override bool CollidingObj - { - get { return false; } - set { return; } - } - - public override PhysicsVector Position - { - get - { - PhysicsVector pos = new PhysicsVector(); - Vec3 vec = _prim.Position; - pos.X = vec.X; - pos.Y = vec.Y; - pos.Z = vec.Z; - return pos; - } - set - { - PhysicsVector vec = value; - Vec3 pos = new Vec3(); - pos.X = vec.X; - pos.Y = vec.Y; - pos.Z = vec.Z; - _prim.Position = pos; - } - } - - public override PrimitiveBaseShape Shape - { - set { return; } - } - - public override PhysicsVector Velocity - { - get { return _velocity; } - set { _velocity = value; } - } - - public override bool Kinematic - { - get { return _prim.Kinematic; } - set { _prim.Kinematic = value; } - } - - public override Quaternion Orientation - { - get - { - Quaternion res = new Quaternion(); - PhysXWrapper.Quaternion quat = _prim.GetOrientation(); - res.w = quat.W; - res.x = quat.X; - res.y = quat.Y; - res.z = quat.Z; - return res; - } - set { } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - public void SetAcceleration(PhysicsVector accel) - { - _acceleration = accel; - } - - public override void AddForce(PhysicsVector force) - { - } - - public override void SetMomentum(PhysicsVector momentum) - { - } - - public override PhysicsVector Size - { - get { return PhysicsVector.Zero; } - set { } - } - - public override float Mass - { - get { return 0f; } - } - - public override PhysicsVector Force - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector CenterOfMass - { - get { return PhysicsVector.Zero; } - } - - public override PhysicsVector GeometricCenter - { - get { return PhysicsVector.Zero; } - } - } -} \ No newline at end of file +/*/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using PhysXWrapper; +using Quaternion=Axiom.Math.Quaternion; + +namespace OpenSim.Region.Physics.PhysXPlugin +{ + /// + /// Will be the PhysX plugin but for now will be a very basic physics engine + /// + public class PhysXPlugin : IPhysicsPlugin + { + private PhysXScene _mScene; + + public PhysXPlugin() + { + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene() + { + if (_mScene == null) + { + _mScene = new PhysXScene(); + } + return (_mScene); + } + + public string GetName() + { + return ("RealPhysX"); + } + + public void Dispose() + { + } + } + + public class PhysXScene : PhysicsScene + { + private List _characters = new List(); + private List _prims = new List(); + private float[] _heightMap = null; + private NxPhysicsSDK mySdk; + private NxScene scene; + + public PhysXScene() + { + mySdk = NxPhysicsSDK.CreateSDK(); + Console.WriteLine("Sdk created - now creating scene"); + scene = mySdk.CreateScene(); + } + + public override void Initialise(IMesher meshmerizer) + { + // Does nothing right now + } + public override void Dispose() + { + + } + + public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) + { + Vec3 pos = new Vec3(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + PhysXCharacter act = new PhysXCharacter(scene.AddCharacter(pos)); + act.Position = position; + _characters.Add(act); + return act; + } + + public override void RemovePrim(PhysicsActor prim) + { + } + + public override void RemoveAvatar(PhysicsActor actor) + { + } + + private PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation, uint localID) + { + Vec3 pos = new Vec3(); + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + Vec3 siz = new Vec3(); + siz.X = size.X; + siz.Y = size.Y; + siz.Z = size.Z; + PhysXPrim act = new PhysXPrim(scene.AddNewBox(pos, siz)); + _prims.Add(act); + return act; + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, uint localID) //To be removed + { + return AddPrimShape(primName, pbs, position, size, rotation, false,localID); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, + PhysicsVector size, Quaternion rotation, bool isPhysical, uint localID) + { + return AddPrim(position, size, rotation,localID); + } + + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + } + + public override float Simulate(float timeStep) + { + float fps = 0f; + try + { + foreach (PhysXCharacter actor in _characters) + { + actor.Move(timeStep); + } + scene.Simulate(timeStep); + scene.FetchResults(); + scene.UpdateControllers(); + + foreach (PhysXCharacter actor in _characters) + { + actor.UpdatePosition(); + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + get { return (false); // for now we won't be multithreaded + } + } + + public override void SetTerrain(float[] heightMap) + { + if (_heightMap != null) + { + Console.WriteLine("PhysX - deleting old terrain"); + scene.DeleteTerrain(); + } + _heightMap = heightMap; + scene.AddTerrain(heightMap); + } + + public override void DeleteTerrain() + { + scene.DeleteTerrain(); + } + } + + public class PhysXCharacter : PhysicsActor + { + private PhysicsVector _position; + private PhysicsVector _velocity; + private PhysicsVector m_rotationalVelocity = PhysicsVector.Zero; + private PhysicsVector _acceleration; + private NxCharacter _character; + private bool flying; + private bool iscolliding = false; + private float gravityAccel; + + public PhysXCharacter(NxCharacter character) + { + _velocity = new PhysicsVector(); + _position = new PhysicsVector(); + _acceleration = new PhysicsVector(); + _character = character; + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get { return _position; } + set + { + _position = value; + Vec3 ps = new Vec3(); + ps.X = value.X; + ps.Y = value.Y; + ps.Z = value.Z; + _character.Position = ps; + } + } + + public override PhysicsVector Size + { + get { return PhysicsVector.Zero; } + set { } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + public void Move(float timeStep) + { + Vec3 vec = new Vec3(); + vec.X = _velocity.X*timeStep; + vec.Y = _velocity.Y*timeStep; + if (flying) + { + vec.Z = (_velocity.Z)*timeStep; + } + else + { + gravityAccel += -9.8f; + vec.Z = (gravityAccel + _velocity.Z)*timeStep; + } + int res = _character.Move(vec); + if (res == 1) + { + gravityAccel = 0; + } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public void UpdatePosition() + { + Vec3 vec = _character.Position; + _position.X = vec.X; + _position.Y = vec.Y; + _position.Z = vec.Z; + } + public override void CrossingFailure() + { + + } + } + + + public class PhysXPrim : PhysicsActor + { + private PhysicsVector _velocity; + private PhysicsVector _acceleration; + private PhysicsVector m_rotationalVelocity; + private NxActor _prim; + + public PhysXPrim(NxActor prim) + { + _velocity = new PhysicsVector(); + _acceleration = new PhysicsVector(); + _prim = prim; + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Prim; } + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override PhysicsVector RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + public override bool Flying + { + get { return false; //no flying prims for you + } + set { } + } + + public override bool IsColliding + { + get { return false; } + set { } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool Stopped + { + get { return false; } + } + + public override PhysicsVector Position + { + get + { + PhysicsVector pos = new PhysicsVector(); + Vec3 vec = _prim.Position; + pos.X = vec.X; + pos.Y = vec.Y; + pos.Z = vec.Z; + return pos; + } + set + { + PhysicsVector vec = value; + Vec3 pos = new Vec3(); + pos.X = vec.X; + pos.Y = vec.Y; + pos.Z = vec.Z; + _prim.Position = pos; + } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override PhysicsVector Velocity + { + get { return _velocity; } + set { _velocity = value; } + } + + public override float CollisionScore + { + get { return 0f; } + } + + public override bool Kinematic + { + get { return _prim.Kinematic; } + set { _prim.Kinematic = value; } + } + + public override Quaternion Orientation + { + get + { + Quaternion res = new Quaternion(); + PhysXWrapper.Quaternion quat = _prim.GetOrientation(); + res.w = quat.W; + res.x = quat.X; + res.y = quat.Y; + res.z = quat.Z; + return res; + } + set { } + } + + public override PhysicsVector Acceleration + { + get { return _acceleration; } + } + + public void SetAcceleration(PhysicsVector accel) + { + _acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + } + + public override void SetMomentum(PhysicsVector momentum) + { + } + + public override PhysicsVector Size + { + get { return PhysicsVector.Zero; } + set { } + } + + public override float Mass + { + get { return 0f; } + } + + public override PhysicsVector Force + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector CenterOfMass + { + get { return PhysicsVector.Zero; } + } + + public override PhysicsVector GeometricCenter + { + get { return PhysicsVector.Zero; } + } + public override void CrossingFailure() + { + + } + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/Executor.cs b/OpenSim/Region/ScriptEngine/Common/Executor.cs index 6f6c3930ff..0f610f804e 100644 --- a/OpenSim/Region/ScriptEngine/Common/Executor.cs +++ b/OpenSim/Region/ScriptEngine/Common/Executor.cs @@ -1,146 +1,92 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.Remoting.Lifetime; - -namespace OpenSim.Region.ScriptEngine.Common -{ - public class Executor : MarshalByRefObject - { - // Private instance for each script - - private IScript m_Script; - private Dictionary Events = new Dictionary(); - private bool m_Running = true; - //private List Scripts = new List(); - - public Executor(IScript Script) - { - m_Script = Script; - } - - // Object never expires - public override Object InitializeLifetimeService() - { - //Console.WriteLine("Executor: InitializeLifetimeService()"); - // return null; - ILease lease = (ILease) base.InitializeLifetimeService(); - - if (lease.CurrentState == LeaseState.Initial) - { - lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); -// lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); -// lease.RenewOnCallTime = TimeSpan.FromSeconds(2); - } - return lease; - } - - public AppDomain GetAppDomain() - { - return AppDomain.CurrentDomain; - } - - public void ExecuteEvent(string FunctionName, object[] args) - { - // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. - // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! - //try - //{ - if (m_Running == false) - { - // Script is inactive, do not execute! - return; - } - - string EventName = m_Script.State() + "_event_" + FunctionName; - -#if DEBUG - Console.WriteLine("ScriptEngine: Script event function name: " + EventName); -#endif - - //type.InvokeMember(EventName, BindingFlags.InvokeMethod, null, m_Script, args); - - //Console.WriteLine("ScriptEngine Executor.ExecuteEvent: \"" + EventName + "\""); - - if (Events.ContainsKey(EventName) == false) - { - // Not found, create - Type type = m_Script.GetType(); - try - { - MethodInfo mi = type.GetMethod(EventName); - Events.Add(EventName, mi); - } - catch - { - // Event name not found, cache it as not found - Events.Add(EventName, null); - } - } - - // Get event - MethodInfo ev = null; - Events.TryGetValue(EventName, out ev); - - if (ev == null) // No event by that name! - { - //Console.WriteLine("ScriptEngine Can not find any event named: \"" + EventName + "\""); - return; - } - -#if DEBUG - Console.WriteLine("ScriptEngine: Executing function name: " + EventName); -#endif - // Found - //try - //{ - // Invoke it - ev.Invoke(m_Script, args); - - //} - //catch (Exception e) - //{ - // // TODO: Send to correct place - // Console.WriteLine("ScriptEngine Exception attempting to executing script function: " + e.ToString()); - //} - - - //} - //catch { } - } - - - public void StopScript() - { - m_Running = false; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.Remoting.Lifetime; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public class Executor : ExecutorBase + { + // Cache functions by keeping a reference to them in a dictionary + private Dictionary Events = new Dictionary(); + + public Executor(IScript script) : base(script) + { + } + + protected override void DoExecuteEvent(string FunctionName, object[] args) + { + // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. + // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! + + string EventName = m_Script.State + "_event_" + FunctionName; + +//#if DEBUG +// Console.WriteLine("ScriptEngine: Script event function name: " + EventName); +//#endif + + if (Events.ContainsKey(EventName) == false) + { + // Not found, create + Type type = m_Script.GetType(); + try + { + MethodInfo mi = type.GetMethod(EventName); + Events.Add(EventName, mi); + } + catch + { + // Event name not found, cache it as not found + Events.Add(EventName, null); + } + } + + // Get event + MethodInfo ev = null; + Events.TryGetValue(EventName, out ev); + + if (ev == null) // No event by that name! + { + //Console.WriteLine("ScriptEngine Can not find any event named: \String.Empty + EventName + "\String.Empty); + return; + } + +//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined +#if DEBUG + Console.WriteLine("ScriptEngine: Executing function name: " + EventName); +#endif + // Found + ev.Invoke(m_Script, args); + + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/ExecutorBase.cs b/OpenSim/Region/ScriptEngine/Common/ExecutorBase.cs new file mode 100644 index 0000000000..4fe4b71ced --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/ExecutorBase.cs @@ -0,0 +1,108 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public abstract class ExecutorBase : MarshalByRefObject + { + /// + /// Contains the script to execute functions in. + /// + protected IScript m_Script; + /// + /// If set to False events will not be executed. + /// + protected bool m_Running = true; + + /// + /// Create a new instance of ExecutorBase + /// + /// + public ExecutorBase(IScript Script) + { + m_Script = Script; + } + + /// + /// Make sure our object does not timeout when in AppDomain. (Called by ILease base class) + /// + /// + public override Object InitializeLifetimeService() + { + //Console.WriteLine("Executor: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + /// + /// Get current AppDomain + /// + /// Current AppDomain + public AppDomain GetAppDomain() + { + return AppDomain.CurrentDomain; + } + + /// + /// Execute a specific function/event in script. + /// + /// Name of function to execute + /// Arguments to pass to function + public void ExecuteEvent(string FunctionName, object[] args) + { + if (m_Running == false) + { + // Script is inactive, do not execute! + return; + } + DoExecuteEvent(FunctionName, args); + } + protected abstract void DoExecuteEvent(string FunctionName, object[] args); + + /// + /// Stop script from running. Event execution will be ignored. + /// + public void StopScript() + { + m_Running = false; + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/IScript.cs b/OpenSim/Region/ScriptEngine/Common/IScript.cs index 30f318f896..0e2a95e9fc 100644 --- a/OpenSim/Region/ScriptEngine/Common/IScript.cs +++ b/OpenSim/Region/ScriptEngine/Common/IScript.cs @@ -1,36 +1,41 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -namespace OpenSim.Region.ScriptEngine.Common -{ - public interface IScript - { - string State(); - Executor Exec { get; } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public interface IScript + { + string State { get; set; } + ExecutorBase Exec { get; } + string Source { get; set; } + void Start(LSL_BuiltIn_Commands_Interface BuiltIn_Commands); + EventQueueManager.Queue_llDetectParams_Struct llDetectParams { get; set; } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs similarity index 94% rename from OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs rename to OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs index 438cdd9633..870884c705 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs @@ -1,2133 +1,2212 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Runtime.Remoting.Lifetime; -using System.Threading; -using OpenSim.Region.ScriptEngine.Common; -using integer = System.Int32; -using key = System.String; -using vector = OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3; -using rotation = OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL -{ - //[Serializable] - public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, IScript - { - - // - // Included as base for any LSL-script that is compiled. - // Any function added here will be accessible to the LSL script. But it must also be added to "LSL_BuiltIn_Commands_Interface" in "OpenSim.Region.ScriptEngine.Common" class. - // - // Security note: This script will be running inside an restricted AppDomain. Currently AppDomain is not very restricted.zxs - // - - // Object never expires - public override Object InitializeLifetimeService() - { - //Console.WriteLine("LSL_BaseClass: InitializeLifetimeService()"); - // return null; - ILease lease = (ILease) base.InitializeLifetimeService(); - - if (lease.CurrentState == LeaseState.Initial) - { - lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); - //lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); - //lease.RenewOnCallTime = TimeSpan.FromSeconds(2); - } - return lease; - } - - - private Executor m_Exec; - - public Executor Exec - { - get - { - if (m_Exec == null) - m_Exec = new Executor(this); - return m_Exec; - } - } - - public LSL_BuiltIn_Commands_Interface m_LSL_Functions; - public string SourceCode = ""; - - public LSL_BaseClass() - { - } - - public string State() - { - return m_LSL_Functions.State(); - } - - - public void Start(LSL_BuiltIn_Commands_Interface LSL_Functions) - { - m_LSL_Functions = LSL_Functions; - - //MainLog.Instance.Notice("ScriptEngine", "LSL_BaseClass.Start() called."); - - // Get this AppDomain's settings and display some of them. - AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation; - Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}", - ads.ApplicationName, - ads.ApplicationBase, - ads.ConfigurationFile - ); - - // Display the name of the calling AppDomain and the name - // of the second domain. - // NOTE: The application's thread has transitioned between - // AppDomains. - Console.WriteLine("Calling to '{0}'.", - Thread.GetDomain().FriendlyName - ); - - return; - } - - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - // They are only forwarders to LSL_BuiltIn_Commands.cs - // - public double llSin(double f) - { - return m_LSL_Functions.llSin(f); - } - - public double llCos(double f) - { - return m_LSL_Functions.llCos(f); - } - - public double llTan(double f) - { - return m_LSL_Functions.llTan(f); - } - - public double llAtan2(double x, double y) - { - return m_LSL_Functions.llAtan2(x, y); - } - - public double llSqrt(double f) - { - return m_LSL_Functions.llSqrt(f); - } - - public double llPow(double fbase, double fexponent) - { - return m_LSL_Functions.llPow(fbase, fexponent); - } - - public int llAbs(int i) - { - return m_LSL_Functions.llAbs(i); - } - - public double llFabs(double f) - { - return m_LSL_Functions.llFabs(f); - } - - public double llFrand(double mag) - { - return m_LSL_Functions.llFrand(mag); - } - - public int llFloor(double f) - { - return m_LSL_Functions.llFloor(f); - } - - public int llCeil(double f) - { - return m_LSL_Functions.llCeil(f); - } - - public int llRound(double f) - { - return m_LSL_Functions.llRound(f); - } - - public double llVecMag(vector v) - { - return m_LSL_Functions.llVecMag(v); - } - - public vector llVecNorm(vector v) - { - return m_LSL_Functions.llVecNorm(v); - } - - public double llVecDist(vector a, vector b) - { - return m_LSL_Functions.llVecDist(a, b); - } - - public vector llRot2Euler(rotation r) - { - return m_LSL_Functions.llRot2Euler(r); - } - - public rotation llEuler2Rot(vector v) - { - return m_LSL_Functions.llEuler2Rot(v); - } - - public rotation llAxes2Rot(vector fwd, vector left, vector up) - { - return m_LSL_Functions.llAxes2Rot(fwd, left, up); - } - - public vector llRot2Fwd(rotation r) - { - return m_LSL_Functions.llRot2Fwd(r); - } - - public vector llRot2Left(rotation r) - { - return m_LSL_Functions.llRot2Left(r); - } - - public vector llRot2Up(rotation r) - { - return m_LSL_Functions.llRot2Up(r); - } - - public rotation llRotBetween(vector start, vector end) - { - return m_LSL_Functions.llRotBetween(start, end); - } - - public void llWhisper(int channelID, string text) - { - m_LSL_Functions.llWhisper(channelID, text); - } - - public void llSay(int channelID, string text) - { - m_LSL_Functions.llSay(channelID, text); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llShout(int channelID, string text) - { - m_LSL_Functions.llShout(channelID, text); - } - - public int llListen(int channelID, string name, string ID, string msg) - { - return m_LSL_Functions.llListen(channelID, name, ID, msg); - } - - public void llListenControl(int number, int active) - { - m_LSL_Functions.llListenControl(number, active); - } - - public void llListenRemove(int number) - { - m_LSL_Functions.llListenRemove(number); - } - - public void llSensor(string name, string id, int type, double range, double arc) - { - m_LSL_Functions.llSensor(name, id, type, range, arc); - } - - public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) - { - m_LSL_Functions.llSensorRepeat(name, id, type, range, arc, rate); - } - - public void llSensorRemove() - { - m_LSL_Functions.llSensorRemove(); - } - - public string llDetectedName(int number) - { - return m_LSL_Functions.llDetectedName(number); - } - - public string llDetectedKey(int number) - { - return m_LSL_Functions.llDetectedKey(number); - } - - public string llDetectedOwner(int number) - { - return m_LSL_Functions.llDetectedOwner(number); - } - - public int llDetectedType(int number) - { - return m_LSL_Functions.llDetectedType(number); - } - - public vector llDetectedPos(int number) - { - return m_LSL_Functions.llDetectedPos(number); - } - - public vector llDetectedVel(int number) - { - return m_LSL_Functions.llDetectedVel(number); - } - - public vector llDetectedGrab(int number) - { - return m_LSL_Functions.llDetectedGrab(number); - } - - public rotation llDetectedRot(int number) - { - return m_LSL_Functions.llDetectedRot(number); - } - - public int llDetectedGroup(int number) - { - return m_LSL_Functions.llDetectedGroup(number); - } - - public int llDetectedLinkNumber(int number) - { - return m_LSL_Functions.llDetectedLinkNumber(number); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llDie() - { - m_LSL_Functions.llDie(); - } - - public double llGround(vector offset) - { - return m_LSL_Functions.llGround(offset); - } - - public double llCloud(vector offset) - { - return m_LSL_Functions.llCloud(offset); - } - - public vector llWind(vector offset) - { - return m_LSL_Functions.llWind(offset); - } - - public void llSetStatus(int status, int value) - { - m_LSL_Functions.llSetStatus(status, value); - } - - public int llGetStatus(int status) - { - return m_LSL_Functions.llGetStatus(status); - } - - public void llSetScale(vector scale) - { - m_LSL_Functions.llSetScale(scale); - } - - public vector llGetScale() - { - return m_LSL_Functions.llGetScale(); - } - - public void llSetColor(vector color, int face) - { - m_LSL_Functions.llSetColor(color, face); - } - - public double llGetAlpha(int face) - { - return m_LSL_Functions.llGetAlpha(face); - } - - public void llSetAlpha(double alpha, int face) - { - m_LSL_Functions.llSetAlpha(alpha, face); - } - - public vector llGetColor(int face) - { - return m_LSL_Functions.llGetColor(face); - } - - public void llSetTexture(string texture, int face) - { - m_LSL_Functions.llSetTexture(texture, face); - } - - public void llScaleTexture(double u, double v, int face) - { - m_LSL_Functions.llScaleTexture(u, v, face); - } - - public void llOffsetTexture(double u, double v, int face) - { - m_LSL_Functions.llOffsetTexture(u, v, face); - } - - public void llRotateTexture(double rotation, int face) - { - m_LSL_Functions.llRotateTexture(rotation, face); - } - - public string llGetTexture(int face) - { - return m_LSL_Functions.llGetTexture(face); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llSetPos(vector pos) - { - m_LSL_Functions.llSetPos(pos); - } - - public vector llGetPos() - { - return m_LSL_Functions.llGetPos(); - } - - public vector llGetLocalPos() - { - return m_LSL_Functions.llGetLocalPos(); - } - - public void llSetRot(rotation rot) - { - m_LSL_Functions.llSetRot(rot); - } - - public rotation llGetRot() - { - return m_LSL_Functions.llGetRot(); - } - - public rotation llGetLocalRot() - { - return m_LSL_Functions.llGetLocalRot(); - } - - public void llSetForce(vector force, int local) - { - m_LSL_Functions.llSetForce(force, local); - } - - public vector llGetForce() - { - return m_LSL_Functions.llGetForce(); - } - - public int llTarget(vector position, double range) - { - return m_LSL_Functions.llTarget(position, range); - } - - public void llTargetRemove(int number) - { - m_LSL_Functions.llTargetRemove(number); - } - - public int llRotTarget(rotation rot, double error) - { - return m_LSL_Functions.llRotTarget(rot, error); - } - - public void llRotTargetRemove(int number) - { - m_LSL_Functions.llRotTargetRemove(number); - } - - public void llMoveToTarget(vector target, double tau) - { - m_LSL_Functions.llMoveToTarget(target, tau); - } - - public void llStopMoveToTarget() - { - m_LSL_Functions.llStopMoveToTarget(); - } - - public void llApplyImpulse(vector force, int local) - { - m_LSL_Functions.llApplyImpulse(force, local); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llApplyRotationalImpulse(vector force, int local) - { - m_LSL_Functions.llApplyRotationalImpulse(force, local); - } - - public void llSetTorque(vector torque, int local) - { - m_LSL_Functions.llSetTorque(torque, local); - } - - public vector llGetTorque() - { - return m_LSL_Functions.llGetTorque(); - } - - public void llSetForceAndTorque(vector force, vector torque, int local) - { - m_LSL_Functions.llSetForceAndTorque(force, torque, local); - } - - public vector llGetVel() - { - return m_LSL_Functions.llGetVel(); - } - - public vector llGetAccel() - { - return m_LSL_Functions.llGetAccel(); - } - - public vector llGetOmega() - { - return m_LSL_Functions.llGetOmega(); - } - - public double llGetTimeOfDay() - { - return m_LSL_Functions.llGetTimeOfDay(); - } - - public double llGetWallclock() - { - return m_LSL_Functions.llGetWallclock(); - } - - public double llGetTime() - { - return m_LSL_Functions.llGetTime(); - } - - public void llResetTime() - { - m_LSL_Functions.llResetTime(); - } - - public double llGetAndResetTime() - { - return m_LSL_Functions.llGetAndResetTime(); - } - - public void llSound() - { - m_LSL_Functions.llSound(); - } - - public void llPlaySound(string sound, double volume) - { - m_LSL_Functions.llPlaySound(sound, volume); - } - - public void llLoopSound(string sound, double volume) - { - m_LSL_Functions.llLoopSound(sound, volume); - } - - public void llLoopSoundMaster(string sound, double volume) - { - m_LSL_Functions.llLoopSoundMaster(sound, volume); - } - - public void llLoopSoundSlave(string sound, double volume) - { - m_LSL_Functions.llLoopSoundSlave(sound, volume); - } - - public void llPlaySoundSlave(string sound, double volume) - { - m_LSL_Functions.llPlaySoundSlave(sound, volume); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llTriggerSound(string sound, double volume) - { - m_LSL_Functions.llTriggerSound(sound, volume); - } - - public void llStopSound() - { - m_LSL_Functions.llStopSound(); - } - - public void llPreloadSound(string sound) - { - m_LSL_Functions.llPreloadSound(sound); - } - - public string llGetSubString(string src, int start, int end) - { - return m_LSL_Functions.llGetSubString(src, start, end); - } - - public string llDeleteSubString(string src, int start, int end) - { - return m_LSL_Functions.llDeleteSubString(src, start, end); - } - - public string llInsertString(string dst, int position, string src) - { - return m_LSL_Functions.llInsertString(dst, position, src); - } - - public string llToUpper(string source) - { - return m_LSL_Functions.llToUpper(source); - } - - public string llToLower(string source) - { - return m_LSL_Functions.llToLower(source); - } - - public int llGiveMoney(string destination, int amount) - { - return m_LSL_Functions.llGiveMoney(destination, amount); - } - - public void llMakeExplosion() - { - m_LSL_Functions.llMakeExplosion(); - } - - public void llMakeFountain() - { - m_LSL_Functions.llMakeFountain(); - } - - public void llMakeSmoke() - { - m_LSL_Functions.llMakeSmoke(); - } - - public void llMakeFire() - { - m_LSL_Functions.llMakeFire(); - } - - public void llRezObject(string inventory, vector pos, rotation rot, int param) - { - m_LSL_Functions.llRezObject(inventory, pos, rot, param); - } - - public void llLookAt(vector target, double strength, double damping) - { - m_LSL_Functions.llLookAt(target, strength, damping); - } - - public void llStopLookAt() - { - m_LSL_Functions.llStopLookAt(); - } - - public void llSetTimerEvent(double sec) - { - m_LSL_Functions.llSetTimerEvent(sec); - } - - public void llSleep(double sec) - { - m_LSL_Functions.llSleep(sec); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public double llGetMass() - { - return m_LSL_Functions.llGetMass(); - } - - public void llCollisionFilter(string name, string id, int accept) - { - m_LSL_Functions.llCollisionFilter(name, id, accept); - } - - public void llTakeControls(int controls, int accept, int pass_on) - { - m_LSL_Functions.llTakeControls(controls, accept, pass_on); - } - - public void llReleaseControls() - { - m_LSL_Functions.llReleaseControls(); - } - - public void llAttachToAvatar(int attachment) - { - m_LSL_Functions.llAttachToAvatar(attachment); - } - - public void llDetachFromAvatar() - { - m_LSL_Functions.llDetachFromAvatar(); - } - - public void llTakeCamera() - { - m_LSL_Functions.llTakeCamera(); - } - - public void llReleaseCamera() - { - m_LSL_Functions.llReleaseCamera(); - } - - public string llGetOwner() - { - return m_LSL_Functions.llGetOwner(); - } - - public void llInstantMessage(string user, string message) - { - m_LSL_Functions.llInstantMessage(user, message); - } - - public void llEmail(string address, string subject, string message) - { - m_LSL_Functions.llEmail(address, subject, message); - } - - public void llGetNextEmail(string address, string subject) - { - m_LSL_Functions.llGetNextEmail(address, subject); - } - - public string llGetKey() - { - return m_LSL_Functions.llGetKey(); - } - - public void llSetBuoyancy(double buoyancy) - { - m_LSL_Functions.llSetBuoyancy(buoyancy); - } - - public void llSetHoverHeight(double height, int water, double tau) - { - m_LSL_Functions.llSetHoverHeight(height, water, tau); - } - - public void llStopHover() - { - m_LSL_Functions.llStopHover(); - } - - public void llMinEventDelay(double delay) - { - m_LSL_Functions.llMinEventDelay(delay); - } - - public void llSoundPreload() - { - m_LSL_Functions.llSoundPreload(); - } - - public void llRotLookAt(rotation target, double strength, double damping) - { - m_LSL_Functions.llRotLookAt(target, strength, damping); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public int llStringLength(string str) - { - return m_LSL_Functions.llStringLength(str); - } - - public void llStartAnimation(string anim) - { - m_LSL_Functions.llStartAnimation(anim); - } - - public void llStopAnimation(string anim) - { - m_LSL_Functions.llStopAnimation(anim); - } - - public void llPointAt() - { - m_LSL_Functions.llPointAt(); - } - - public void llStopPointAt() - { - m_LSL_Functions.llStopPointAt(); - } - - public void llTargetOmega(vector axis, double spinrate, double gain) - { - m_LSL_Functions.llTargetOmega(axis, spinrate, gain); - } - - public int llGetStartParameter() - { - return m_LSL_Functions.llGetStartParameter(); - } - - public void llGodLikeRezObject(string inventory, vector pos) - { - m_LSL_Functions.llGodLikeRezObject(inventory, pos); - } - - public void llRequestPermissions(string agent, int perm) - { - m_LSL_Functions.llRequestPermissions(agent, perm); - } - - public string llGetPermissionsKey() - { - return m_LSL_Functions.llGetPermissionsKey(); - } - - public int llGetPermissions() - { - return m_LSL_Functions.llGetPermissions(); - } - - public int llGetLinkNumber() - { - return m_LSL_Functions.llGetLinkNumber(); - } - - public void llSetLinkColor(int linknumber, vector color, int face) - { - m_LSL_Functions.llSetLinkColor(linknumber, color, face); - } - - public void llCreateLink(string target, int parent) - { - m_LSL_Functions.llCreateLink(target, parent); - } - - public void llBreakLink(int linknum) - { - m_LSL_Functions.llBreakLink(linknum); - } - - public void llBreakAllLinks() - { - m_LSL_Functions.llBreakAllLinks(); - } - - public string llGetLinkKey(int linknum) - { - return m_LSL_Functions.llGetLinkKey(linknum); - } - - public string llGetLinkName(int linknum) - { - return m_LSL_Functions.llGetLinkName(linknum); - } - - public int llGetInventoryNumber(int type) - { - return m_LSL_Functions.llGetInventoryNumber(type); - } - - public string llGetInventoryName(int type, int number) - { - return m_LSL_Functions.llGetInventoryName(type, number); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llSetScriptState(string name, int run) - { - m_LSL_Functions.llSetScriptState(name, run); - } - - public double llGetEnergy() - { - return m_LSL_Functions.llGetEnergy(); - } - - public void llGiveInventory(string destination, string inventory) - { - m_LSL_Functions.llGiveInventory(destination, inventory); - } - - public void llRemoveInventory(string item) - { - m_LSL_Functions.llRemoveInventory(item); - } - - public void llSetText(string text, vector color, double alpha) - { - m_LSL_Functions.llSetText(text, color, alpha); - } - - public double llWater(vector offset) - { - return m_LSL_Functions.llWater(offset); - } - - public void llPassTouches(int pass) - { - m_LSL_Functions.llPassTouches(pass); - } - - public string llRequestAgentData(string id, int data) - { - return m_LSL_Functions.llRequestAgentData(id, data); - } - - public string llRequestInventoryData(string name) - { - return m_LSL_Functions.llRequestInventoryData(name); - } - - public void llSetDamage(double damage) - { - m_LSL_Functions.llSetDamage(damage); - } - - public void llTeleportAgentHome(string agent) - { - m_LSL_Functions.llTeleportAgentHome(agent); - } - - public void llModifyLand(int action, int brush) - { - m_LSL_Functions.llModifyLand(action, brush); - } - - public void llCollisionSound(string impact_sound, double impact_volume) - { - m_LSL_Functions.llCollisionSound(impact_sound, impact_volume); - } - - public void llCollisionSprite(string impact_sprite) - { - m_LSL_Functions.llCollisionSprite(impact_sprite); - } - - public string llGetAnimation(string id) - { - return m_LSL_Functions.llGetAnimation(id); - } - - public void llResetScript() - { - m_LSL_Functions.llResetScript(); - } - - public void llMessageLinked(int linknum, int num, string str, string id) - { - m_LSL_Functions.llMessageLinked(linknum, num, str, id); - } - - public void llPushObject(string target, vector impulse, vector ang_impulse, int local) - { - m_LSL_Functions.llPushObject(target, impulse, ang_impulse, local); - } - - public void llPassCollisions(int pass) - { - m_LSL_Functions.llPassCollisions(pass); - } - - public string llGetScriptName() - { - return m_LSL_Functions.llGetScriptName(); - } - - public int llGetNumberOfSides() - { - return m_LSL_Functions.llGetNumberOfSides(); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public rotation llAxisAngle2Rot(vector axis, double angle) - { - return m_LSL_Functions.llAxisAngle2Rot(axis, angle); - } - - public vector llRot2Axis(rotation rot) - { - return m_LSL_Functions.llRot2Axis(rot); - } - - public void llRot2Angle() - { - m_LSL_Functions.llRot2Angle(); - } - - public double llAcos(double val) - { - return m_LSL_Functions.llAcos(val); - } - - public double llAsin(double val) - { - return m_LSL_Functions.llAsin(val); - } - - public double llAngleBetween(rotation a, rotation b) - { - return m_LSL_Functions.llAngleBetween(a, b); - } - - public string llGetInventoryKey(string name) - { - return m_LSL_Functions.llGetInventoryKey(name); - } - - public void llAllowInventoryDrop(int add) - { - m_LSL_Functions.llAllowInventoryDrop(add); - } - - public vector llGetSunDirection() - { - return m_LSL_Functions.llGetSunDirection(); - } - - public vector llGetTextureOffset(int face) - { - return m_LSL_Functions.llGetTextureOffset(face); - } - - public vector llGetTextureScale(int side) - { - return m_LSL_Functions.llGetTextureScale(side); - } - - public double llGetTextureRot(int side) - { - return m_LSL_Functions.llGetTextureRot(side); - } - - public int llSubStringIndex(string source, string pattern) - { - return m_LSL_Functions.llSubStringIndex(source, pattern); - } - - public string llGetOwnerKey(string id) - { - return m_LSL_Functions.llGetOwnerKey(id); - } - - public vector llGetCenterOfMass() - { - return m_LSL_Functions.llGetCenterOfMass(); - } - - public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending) - { - return m_LSL_Functions.llListSort(src, stride, ascending); - } - - public int llGetListLength(LSL_Types.list src) - { - return m_LSL_Functions.llGetListLength(src); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public int llList2Integer(LSL_Types.list src, int index) - { - return m_LSL_Functions.llList2Integer(src, index); - } - - public double osList2Double(LSL_Types.list src, int index) - { - return m_LSL_Functions.osList2Double(src, index); - } - - public string llList2String(LSL_Types.list src, int index) - { - return m_LSL_Functions.llList2String(src, index); - } - - public string llList2Key(LSL_Types.list src, int index) - { - return m_LSL_Functions.llList2Key(src, index); - } - - public vector llList2Vector(LSL_Types.list src, int index) - { - return m_LSL_Functions.llList2Vector(src, index); - } - - public rotation llList2Rot(LSL_Types.list src, int index) - { - return m_LSL_Functions.llList2Rot(src, index); - } - - public LSL_Types.list llList2List(LSL_Types.list src, int start, int end) - { - return m_LSL_Functions.llList2List(src, start, end); - } - - public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end) - { - return m_LSL_Functions.llDeleteSubList(src, start, end); - } - - public int llGetListEntryType(LSL_Types.list src, int index) - { - return m_LSL_Functions.llGetListEntryType(src, index); - } - - public string llList2CSV(LSL_Types.list src) - { - return m_LSL_Functions.llList2CSV(src); - } - - public LSL_Types.list llCSV2List(string src) - { - return m_LSL_Functions.llCSV2List(src); - } - - public LSL_Types.list llListRandomize(LSL_Types.list src, int stride) - { - return m_LSL_Functions.llListRandomize(src, stride); - } - - public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride) - { - return m_LSL_Functions.llList2ListStrided(src, start, end, stride); - } - - public vector llGetRegionCorner() - { - return m_LSL_Functions.llGetRegionCorner(); - } - - public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start) - { - return m_LSL_Functions.llListInsertList(dest, src, start); - } - - public int llListFindList(LSL_Types.list src, LSL_Types.list test) - { - return m_LSL_Functions.llListFindList(src, test); - } - - public string llGetObjectName() - { - return m_LSL_Functions.llGetObjectName(); - } - - public void llSetObjectName(string name) - { - m_LSL_Functions.llSetObjectName(name); - } - - public string llGetDate() - { - return m_LSL_Functions.llGetDate(); - } - - public int llEdgeOfWorld(vector pos, vector dir) - { - return m_LSL_Functions.llEdgeOfWorld(pos, dir); - } - - public int llGetAgentInfo(string id) - { - return m_LSL_Functions.llGetAgentInfo(id); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llAdjustSoundVolume(double volume) - { - m_LSL_Functions.llAdjustSoundVolume(volume); - } - - public void llSetSoundQueueing(int queue) - { - m_LSL_Functions.llSetSoundQueueing(queue); - } - - public void llSetSoundRadius(double radius) - { - m_LSL_Functions.llSetSoundRadius(radius); - } - - public string llKey2Name(string id) - { - return m_LSL_Functions.llKey2Name(id); - } - - public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) - { - m_LSL_Functions.llSetTextureAnim(mode, face, sizex, sizey, start, length, rate); - } - - public void llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) - { - m_LSL_Functions.llTriggerSoundLimited(sound, volume, top_north_east, bottom_south_west); - } - - public void llEjectFromLand(string pest) - { - m_LSL_Functions.llEjectFromLand(pest); - } - - public void llParseString2List() - { - m_LSL_Functions.llParseString2List(); - } - - public int llOverMyLand(string id) - { - return m_LSL_Functions.llOverMyLand(id); - } - - public string llGetLandOwnerAt(vector pos) - { - return m_LSL_Functions.llGetLandOwnerAt(pos); - } - - public string llGetNotecardLine(string name, int line) - { - return m_LSL_Functions.llGetNotecardLine(name, line); - } - - public vector llGetAgentSize(string id) - { - return m_LSL_Functions.llGetAgentSize(id); - } - - public int llSameGroup(string agent) - { - return m_LSL_Functions.llSameGroup(agent); - } - - public void llUnSit(string id) - { - m_LSL_Functions.llUnSit(id); - } - - public vector llGroundSlope(vector offset) - { - return m_LSL_Functions.llGroundSlope(offset); - } - - public vector llGroundNormal(vector offset) - { - return m_LSL_Functions.llGroundNormal(offset); - } - - public vector llGroundContour(vector offset) - { - return m_LSL_Functions.llGroundContour(offset); - } - - public int llGetAttached() - { - return m_LSL_Functions.llGetAttached(); - } - - public int llGetFreeMemory() - { - return m_LSL_Functions.llGetFreeMemory(); - } - - public string llGetRegionName() - { - return m_LSL_Functions.llGetRegionName(); - } - - public double llGetRegionTimeDilation() - { - return m_LSL_Functions.llGetRegionTimeDilation(); - } - - public double llGetRegionFPS() - { - return m_LSL_Functions.llGetRegionFPS(); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llParticleSystem(List rules) - { - m_LSL_Functions.llParticleSystem(rules); - } - - public void llGroundRepel(double height, int water, double tau) - { - m_LSL_Functions.llGroundRepel(height, water, tau); - } - - public void llGiveInventoryList() - { - m_LSL_Functions.llGiveInventoryList(); - } - - public void llSetVehicleType(int type) - { - m_LSL_Functions.llSetVehicleType(type); - } - - public void llSetVehicledoubleParam(int param, double value) - { - m_LSL_Functions.llSetVehicledoubleParam(param, value); - } - - public void llSetVehicleVectorParam(int param, vector vec) - { - m_LSL_Functions.llSetVehicleVectorParam(param, vec); - } - - public void llSetVehicleRotationParam(int param, rotation rot) - { - m_LSL_Functions.llSetVehicleRotationParam(param, rot); - } - - public void llSetVehicleFlags(int flags) - { - m_LSL_Functions.llSetVehicleFlags(flags); - } - - public void llRemoveVehicleFlags(int flags) - { - m_LSL_Functions.llRemoveVehicleFlags(flags); - } - - public void llSitTarget(vector offset, rotation rot) - { - m_LSL_Functions.llSitTarget(offset, rot); - } - - public string llAvatarOnSitTarget() - { - return m_LSL_Functions.llAvatarOnSitTarget(); - } - - public void llAddToLandPassList(string avatar, double hours) - { - m_LSL_Functions.llAddToLandPassList(avatar, hours); - } - - public void llSetTouchText(string text) - { - m_LSL_Functions.llSetTouchText(text); - } - - public void llSetSitText(string text) - { - m_LSL_Functions.llSetSitText(text); - } - - public void llSetCameraEyeOffset(vector offset) - { - m_LSL_Functions.llSetCameraEyeOffset(offset); - } - - public void llSetCameraAtOffset(vector offset) - { - m_LSL_Functions.llSetCameraAtOffset(offset); - } - - public string llDumpList2String(LSL_Types.list src, string seperator) - { - return m_LSL_Functions.llDumpList2String(src, seperator); - } - - public void llScriptDanger(vector pos) - { - m_LSL_Functions.llScriptDanger(pos); - } - - public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel) - { - m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); - } - - public void llVolumeDetect(int detect) - { - m_LSL_Functions.llVolumeDetect(detect); - } - - public void llResetOtherScript(string name) - { - m_LSL_Functions.llResetOtherScript(name); - } - - public int llGetScriptState(string name) - { - return m_LSL_Functions.llGetScriptState(name); - } - - public void llRemoteLoadScript() - { - m_LSL_Functions.llRemoteLoadScript(); - } - - public void llSetRemoteScriptAccessPin(int pin) - { - m_LSL_Functions.llSetRemoteScriptAccessPin(pin); - } - - public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) - { - m_LSL_Functions.llRemoteLoadScriptPin(target, name, pin, running, start_param); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public void llOpenRemoteDataChannel() - { - m_LSL_Functions.llOpenRemoteDataChannel(); - } - - public string llSendRemoteData(string channel, string dest, int idata, string sdata) - { - return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata); - } - - public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) - { - m_LSL_Functions.llRemoteDataReply(channel, message_id, sdata, idata); - } - - public void llCloseRemoteDataChannel(string channel) - { - m_LSL_Functions.llCloseRemoteDataChannel(channel); - } - - public string llMD5String(string src, int nonce) - { - return m_LSL_Functions.llMD5String(src, nonce); - } - - public void llSetPrimitiveParams(LSL_Types.list rules) - { - m_LSL_Functions.llSetPrimitiveParams(rules); - } - - public string llStringToBase64(string str) - { - return m_LSL_Functions.llStringToBase64(str); - } - - public string llBase64ToString(string str) - { - return m_LSL_Functions.llBase64ToString(str); - } - - public void llXorBase64Strings() - { - m_LSL_Functions.llXorBase64Strings(); - } - - public void llRemoteDataSetRegion() - { - m_LSL_Functions.llRemoteDataSetRegion(); - } - - public double llLog10(double val) - { - return m_LSL_Functions.llLog10(val); - } - - public double llLog(double val) - { - return m_LSL_Functions.llLog(val); - } - - public LSL_Types.list llGetAnimationList(string id) - { - return m_LSL_Functions.llGetAnimationList(id); - } - - public void llSetParcelMusicURL(string url) - { - m_LSL_Functions.llSetParcelMusicURL(url); - } - - public vector llGetRootPosition() - { - return m_LSL_Functions.llGetRootPosition(); - } - - public rotation llGetRootRotation() - { - return m_LSL_Functions.llGetRootRotation(); - } - - public string llGetObjectDesc() - { - return m_LSL_Functions.llGetObjectDesc(); - } - - public void llSetObjectDesc(string desc) - { - m_LSL_Functions.llSetObjectDesc(desc); - } - - public string llGetCreator() - { - return m_LSL_Functions.llGetCreator(); - } - - public string llGetTimestamp() - { - return m_LSL_Functions.llGetTimestamp(); - } - - public void llSetLinkAlpha(int linknumber, double alpha, int face) - { - m_LSL_Functions.llSetLinkAlpha(linknumber, alpha, face); - } - - public int llGetNumberOfPrims() - { - return m_LSL_Functions.llGetNumberOfPrims(); - } - - public string llGetNumberOfNotecardLines(string name) - { - return m_LSL_Functions.llGetNumberOfNotecardLines(name); - } - - public LSL_Types.list llGetBoundingBox(string obj) - { - return m_LSL_Functions.llGetBoundingBox(obj); - } - - public vector llGetGeometricCenter() - { - return m_LSL_Functions.llGetGeometricCenter(); - } - - public void llGetPrimitiveParams() - { - m_LSL_Functions.llGetPrimitiveParams(); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public string llIntegerToBase64(int number) - { - return m_LSL_Functions.llIntegerToBase64(number); - } - - public int llBase64ToInteger(string str) - { - return m_LSL_Functions.llBase64ToInteger(str); - } - - public double llGetGMTclock() - { - return m_LSL_Functions.llGetGMTclock(); - } - - public string llGetSimulatorHostname() - { - return m_LSL_Functions.llGetSimulatorHostname(); - } - - public void llSetLocalRot(rotation rot) - { - m_LSL_Functions.llSetLocalRot(rot); - } - - public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers) - { - return m_LSL_Functions.llParseStringKeepNulls(src, seperators, spacers); - } - - public void llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, int param) - { - m_LSL_Functions.llRezAtRoot(inventory, position, velocity, rot, param); - } - - public int llGetObjectPermMask(int mask) - { - return m_LSL_Functions.llGetObjectPermMask(mask); - } - - public void llSetObjectPermMask(int mask, int value) - { - m_LSL_Functions.llSetObjectPermMask(mask, value); - } - - public void llGetInventoryPermMask(string item, int mask) - { - m_LSL_Functions.llGetInventoryPermMask(item, mask); - } - - public void llSetInventoryPermMask(string item, int mask, int value) - { - m_LSL_Functions.llSetInventoryPermMask(item, mask, value); - } - - public string llGetInventoryCreator(string item) - { - return m_LSL_Functions.llGetInventoryCreator(item); - } - - public void llOwnerSay(string msg) - { - m_LSL_Functions.llOwnerSay(msg); - } - - public void llRequestSimulatorData(string simulator, int data) - { - m_LSL_Functions.llRequestSimulatorData(simulator, data); - } - - public void llForceMouselook(int mouselook) - { - m_LSL_Functions.llForceMouselook(mouselook); - } - - public double llGetObjectMass(string id) - { - return m_LSL_Functions.llGetObjectMass(id); - } - - public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end) - { - return m_LSL_Functions.llListReplaceList(dest, src, start, end); - } - - public void llLoadURL(string avatar_id, string message, string url) - { - m_LSL_Functions.llLoadURL(avatar_id, message, url); - } - - public void llParcelMediaCommandList(LSL_Types.list commandList) - { - m_LSL_Functions.llParcelMediaCommandList(commandList); - } - - public void llParcelMediaQuery() - { - m_LSL_Functions.llParcelMediaQuery(); - } - - public int llModPow(int a, int b, int c) - { - return m_LSL_Functions.llModPow(a, b, c); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public int llGetInventoryType(string name) - { - return m_LSL_Functions.llGetInventoryType(name); - } - - public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) - { - m_LSL_Functions.llSetPayPrice(price, quick_pay_buttons); - } - - public vector llGetCameraPos() - { - return m_LSL_Functions.llGetCameraPos(); - } - - public rotation llGetCameraRot() - { - return m_LSL_Functions.llGetCameraRot(); - } - - public void llSetPrimURL() - { - m_LSL_Functions.llSetPrimURL(); - } - - public void llRefreshPrimURL() - { - m_LSL_Functions.llRefreshPrimURL(); - } - - public string llEscapeURL(string url) - { - return m_LSL_Functions.llEscapeURL(url); - } - - public string llUnescapeURL(string url) - { - return m_LSL_Functions.llUnescapeURL(url); - } - - public void llMapDestination(string simname, vector pos, vector look_at) - { - m_LSL_Functions.llMapDestination(simname, pos, look_at); - } - - public void llAddToLandBanList(string avatar, double hours) - { - m_LSL_Functions.llAddToLandBanList(avatar, hours); - } - - public void llRemoveFromLandPassList(string avatar) - { - m_LSL_Functions.llRemoveFromLandPassList(avatar); - } - - public void llRemoveFromLandBanList(string avatar) - { - m_LSL_Functions.llRemoveFromLandBanList(avatar); - } - - public void llSetCameraParams(LSL_Types.list rules) - { - m_LSL_Functions.llSetCameraParams(rules); - } - - public void llClearCameraParams() - { - m_LSL_Functions.llClearCameraParams(); - } - - public double llListStatistics(int operation, LSL_Types.list src) - { - return m_LSL_Functions.llListStatistics(operation, src); - } - - public int llGetUnixTime() - { - return m_LSL_Functions.llGetUnixTime(); - } - - public int llGetParcelFlags(vector pos) - { - return m_LSL_Functions.llGetParcelFlags(pos); - } - - public int llGetRegionFlags() - { - return m_LSL_Functions.llGetRegionFlags(); - } - - public string llXorBase64StringsCorrect(string str1, string str2) - { - return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2); - } - - public string llHTTPRequest(string url, LSL_Types.list parameters, string body) - { - return m_LSL_Functions.llHTTPRequest(url, parameters, body); - } - - public void llResetLandBanList() - { - m_LSL_Functions.llResetLandBanList(); - } - - public void llResetLandPassList() - { - m_LSL_Functions.llResetLandPassList(); - } - - public int llGetParcelPrimCount(vector pos, int category, int sim_wide) - { - return m_LSL_Functions.llGetParcelPrimCount(pos, category, sim_wide); - } - - public LSL_Types.list llGetParcelPrimOwners(vector pos) - { - return m_LSL_Functions.llGetParcelPrimOwners(pos); - } - - public int llGetObjectPrimCount(string object_id) - { - return m_LSL_Functions.llGetObjectPrimCount(object_id); - } - - // - // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs - // - public int llGetParcelMaxPrims(vector pos, int sim_wide) - { - return m_LSL_Functions.llGetParcelMaxPrims(pos, sim_wide); - } - - public LSL_Types.list llGetParcelDetails(vector pos, LSL_Types.list param) - { - return m_LSL_Functions.llGetParcelDetails(pos, param); - } - - // - // OpenSim Functions - // - public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, - int timer) - { - return m_LSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer); - } - - // LSL CONSTANTS - public const int TRUE = 1; - public const int FALSE = 0; - public const int STATUS_PHYSICS = 1; - public const int STATUS_ROTATE_X = 2; - public const int STATUS_ROTATE_Y = 4; - public const int STATUS_ROTATE_Z = 8; - public const int STATUS_PHANTOM = 16; - public const int STATUS_SANDBOX = 32; - public const int STATUS_BLOCK_GRAB = 64; - public const int STATUS_DIE_AT_EDGE = 128; - public const int STATUS_RETURN_AT_EDGE = 256; - public const int AGENT = 1; - public const int ACTIVE = 2; - public const int PASSIVE = 4; - public const int SCRIPTED = 8; - public const int CONTROL_FWD = 1; - public const int CONTROL_BACK = 2; - public const int CONTROL_LEFT = 4; - public const int CONTROL_RIGHT = 8; - public const int CONTROL_UP = 16; - public const int CONTROL_DOWN = 32; - public const int CONTROL_ROT_LEFT = 256; - public const int CONTROL_ROT_RIGHT = 512; - public const int CONTROL_LBUTTON = 268435456; - public const int CONTROL_ML_LBUTTON = 1073741824; - public const int PERMISSION_DEBIT = 2; - public const int PERMISSION_TAKE_CONTROLS = 4; - public const int PERMISSION_REMAP_CONTROLS = 8; - public const int PERMISSION_TRIGGER_ANIMATION = 16; - public const int PERMISSION_ATTACH = 32; - public const int PERMISSION_RELEASE_OWNERSHIP = 64; - public const int PERMISSION_CHANGE_LINKS = 128; - public const int PERMISSION_CHANGE_JOINTS = 256; - public const int PERMISSION_CHANGE_PERMISSIONS = 512; - public const int PERMISSION_TRACK_CAMERA = 1024; - public const int AGENT_FLYING = 1; - public const int AGENT_ATTACHMENTS = 2; - public const int AGENT_SCRIPTED = 4; - public const int AGENT_MOUSELOOK = 8; - public const int AGENT_SITTING = 16; - public const int AGENT_ON_OBJECT = 32; - public const int AGENT_AWAY = 64; - public const int AGENT_WALKING = 128; - public const int AGENT_IN_AIR = 256; - public const int AGENT_TYPING = 512; - public const int AGENT_CROUCHING = 1024; - public const int AGENT_BUSY = 2048; - public const int AGENT_ALWAYS_RUN = 4096; - public const int PSYS_PART_INTERP_COLOR_MASK = 1; - public const int PSYS_PART_INTERP_SCALE_MASK = 2; - public const int PSYS_PART_BOUNCE_MASK = 4; - public const int PSYS_PART_WIND_MASK = 8; - public const int PSYS_PART_FOLLOW_SRC_MASK = 16; - public const int PSYS_PART_FOLLOW_VELOCITY_MASK = 32; - public const int PSYS_PART_TARGET_POS_MASK = 64; - public const int PSYS_PART_TARGET_LINEAR_MASK = 128; - public const int PSYS_PART_EMISSIVE_MASK = 256; - public const int PSYS_PART_FLAGS = 0; - public const int PSYS_PART_START_COLOR = 1; - public const int PSYS_PART_START_ALPHA = 2; - public const int PSYS_PART_END_COLOR = 3; - public const int PSYS_PART_END_ALPHA = 4; - public const int PSYS_PART_START_SCALE = 5; - public const int PSYS_PART_END_SCALE = 6; - public const int PSYS_PART_MAX_AGE = 7; - public const int PSYS_SRC_ACCEL = 8; - public const int PSYS_SRC_PATTERN = 9; - public const int PSYS_SRC_INNERANGLE = 10; - public const int PSYS_SRC_OUTERANGLE = 11; - public const int PSYS_SRC_TEXTURE = 12; - public const int PSYS_SRC_BURST_RATE = 13; - public const int PSYS_SRC_BURST_PART_COUNT = 15; - public const int PSYS_SRC_BURST_RADIUS = 16; - public const int PSYS_SRC_BURST_SPEED_MIN = 17; - public const int PSYS_SRC_BURST_SPEED_MAX = 18; - public const int PSYS_SRC_MAX_AGE = 19; - public const int PSYS_SRC_TARGET_KEY = 20; - public const int PSYS_SRC_OMEGA = 21; - public const int PSYS_SRC_ANGLE_BEGIN = 22; - public const int PSYS_SRC_ANGLE_END = 23; - public const int PSYS_SRC_PATTERN_DROP = 1; - public const int PSYS_SRC_PATTERN_EXPLODE = 2; - public const int PSYS_SRC_PATTERN_ANGLE = 4; - public const int PSYS_SRC_PATTERN_ANGLE_CONE = 8; - public const int PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY = 16; - public const int VEHICLE_TYPE_NONE = 0; - public const int VEHICLE_TYPE_SLED = 1; - public const int VEHICLE_TYPE_CAR = 2; - public const int VEHICLE_TYPE_BOAT = 3; - public const int VEHICLE_TYPE_AIRPLANE = 4; - public const int VEHICLE_TYPE_BALLOON = 5; - public const int VEHICLE_LINEAR_FRICTION_TIMESCALE = 16; - public const int VEHICLE_ANGULAR_FRICTION_TIMESCALE = 17; - public const int VEHICLE_LINEAR_MOTOR_DIRECTION = 18; - public const int VEHICLE_LINEAR_MOTOR_OFFSET = 20; - public const int VEHICLE_ANGULAR_MOTOR_DIRECTION = 19; - public const int VEHICLE_HOVER_HEIGHT = 24; - public const int VEHICLE_HOVER_EFFICIENCY = 25; - public const int VEHICLE_HOVER_TIMESCALE = 26; - public const int VEHICLE_BUOYANCY = 27; - public const int VEHICLE_LINEAR_DEFLECTION_EFFICIENCY = 28; - public const int VEHICLE_LINEAR_DEFLECTION_TIMESCALE = 29; - public const int VEHICLE_LINEAR_MOTOR_TIMESCALE = 30; - public const int VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE = 31; - public const int VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY = 32; - public const int VEHICLE_ANGULAR_DEFLECTION_TIMESCALE = 33; - public const int VEHICLE_ANGULAR_MOTOR_TIMESCALE = 34; - public const int VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE = 35; - public const int VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY = 36; - public const int VEHICLE_VERTICAL_ATTRACTION_TIMESCALE = 37; - public const int VEHICLE_BANKING_EFFICIENCY = 38; - public const int VEHICLE_BANKING_MIX = 39; - public const int VEHICLE_BANKING_TIMESCALE = 40; - public const int VEHICLE_REFERENCE_FRAME = 44; - public const int VEHICLE_FLAG_NO_DEFLECTION_UP = 1; - public const int VEHICLE_FLAG_LIMIT_ROLL_ONLY = 2; - public const int VEHICLE_FLAG_HOVER_WATER_ONLY = 4; - public const int VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 8; - public const int VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT = 16; - public const int VEHICLE_FLAG_HOVER_UP_ONLY = 32; - public const int VEHICLE_FLAG_LIMIT_MOTOR_UP = 64; - public const int VEHICLE_FLAG_MOUSELOOK_STEER = 128; - public const int VEHICLE_FLAG_MOUSELOOK_BANK = 256; - public const int VEHICLE_FLAG_CAMERA_DECOUPLED = 512; - public const int INVENTORY_ALL = -1; - public const int INVENTORY_NONE = -1; - public const int INVENTORY_TEXTURE = 0; - public const int INVENTORY_SOUND = 1; - public const int INVENTORY_LANDMARK = 3; - public const int INVENTORY_CLOTHING = 5; - public const int INVENTORY_OBJECT = 6; - public const int INVENTORY_NOTECARD = 7; - public const int INVENTORY_SCRIPT = 10; - public const int INVENTORY_BODYPART = 13; - public const int INVENTORY_ANIMATION = 20; - public const int INVENTORY_GESTURE = 21; - public const int ATTACH_CHEST = 1; - public const int ATTACH_HEAD = 2; - public const int ATTACH_LSHOULDER = 3; - public const int ATTACH_RSHOULDER = 4; - public const int ATTACH_LHAND = 5; - public const int ATTACH_RHAND = 6; - public const int ATTACH_LFOOT = 7; - public const int ATTACH_RFOOT = 8; - public const int ATTACH_BACK = 9; - public const int ATTACH_PELVIS = 10; - public const int ATTACH_MOUTH = 11; - public const int ATTACH_CHIN = 12; - public const int ATTACH_LEAR = 13; - public const int ATTACH_REAR = 14; - public const int ATTACH_LEYE = 15; - public const int ATTACH_REYE = 16; - public const int ATTACH_NOSE = 17; - public const int ATTACH_RUARM = 18; - public const int ATTACH_RLARM = 19; - public const int ATTACH_LUARM = 20; - public const int ATTACH_LLARM = 21; - public const int ATTACH_RHIP = 22; - public const int ATTACH_RULEG = 23; - public const int ATTACH_RLLEG = 24; - public const int ATTACH_LHIP = 25; - public const int ATTACH_LULEG = 26; - public const int ATTACH_LLLEG = 27; - public const int ATTACH_BELLY = 28; - public const int ATTACH_RPEC = 29; - public const int ATTACH_LPEC = 30; - public const int LAND_LEVEL = 0; - public const int LAND_RAISE = 1; - public const int LAND_LOWER = 2; - public const int LAND_SMOOTH = 3; - public const int LAND_NOISE = 4; - public const int LAND_REVERT = 5; - public const int LAND_SMALL_BRUSH = 1; - public const int LAND_MEDIUM_BRUSH = 2; - public const int LAND_LARGE_BRUSH = 3; - public const int DATA_ONLINE = 1; - public const int DATA_NAME = 2; - public const int DATA_BORN = 3; - public const int DATA_RATING = 4; - public const int DATA_SIM_POS = 5; - public const int DATA_SIM_STATUS = 6; - public const int DATA_SIM_RATING = 7; - public const int ANIM_ON = 1; - public const int LOOP = 2; - public const int REVERSE = 4; - public const int PING_PONG = 8; - public const int SMOOTH = 16; - public const int ROTATE = 32; - public const int SCALE = 64; - public const int ALL_SIDES = -1; - public const int LINK_SET = -1; - public const int LINK_ROOT = 1; - public const int LINK_ALL_OTHERS = -2; - public const int LINK_ALL_CHILDREN = -3; - public const int LINK_THIS = -4; - public const int CHANGED_INVENTORY = 1; - public const int CHANGED_COLOR = 2; - public const int CHANGED_SHAPE = 4; - public const int CHANGED_SCALE = 8; - public const int CHANGED_TEXTURE = 16; - public const int CHANGED_LINK = 32; - public const int CHANGED_ALLOWED_DROP = 64; - public const int CHANGED_OWNER = 128; - public const int TYPE_INVALID = 0; - public const int TYPE_INTEGER = 1; - public const int TYPE_double = 2; - public const int TYPE_STRING = 3; - public const int TYPE_KEY = 4; - public const int TYPE_VECTOR = 5; - public const int TYPE_ROTATION = 6; - public const int REMOTE_DATA_CHANNEL = 1; - public const int REMOTE_DATA_REQUEST = 2; - public const int REMOTE_DATA_REPLY = 3; - - public const int PRIM_MATERIAL = 2; - public const int PRIM_PHYSICS = 3; - public const int PRIM_TEMP_ON_REZ = 4; - public const int PRIM_PHANTOM = 5; - public const int PRIM_POSITION = 6; - public const int PRIM_SIZE = 7; - public const int PRIM_ROTATION = 8; - public const int PRIM_TYPE = 9; - public const int PRIM_TEXTURE = 17; - public const int PRIM_COLOR = 18; - public const int PRIM_BUMP_SHINY = 19; - public const int PRIM_FULLBRIGHT = 20; - public const int PRIM_FLEXIBLE = 21; - public const int PRIM_TEXGEN = 22; - public const int PRIM_CAST_SHADOWS = 24; // Not implemented, here for completeness sake - public const int PRIM_POINT_LIGHT = 23; // Huh? - public const int PRIM_TEXGEN_DEFAULT = 0; - public const int PRIM_TEXGEN_PLANAR = 1; - public const int PRIM_TYPE_BOX = 0; - public const int PRIM_TYPE_CYLINDER = 1; - public const int PRIM_TYPE_PRISM = 2; - public const int PRIM_TYPE_SPHERE = 3; - public const int PRIM_TYPE_TORUS = 4; - public const int PRIM_TYPE_TUBE = 5; - public const int PRIM_TYPE_RING = 6; - public const int PRIM_TYPE_SCULPT = 7; - public const int PRIM_HOLE_DEFAULT = 0; - public const int PRIM_HOLE_CIRCLE = 16; - public const int PRIM_HOLE_SQUARE = 32; - public const int PRIM_HOLE_TRIANGLE = 48; - public const int PRIM_MATERIAL_STONE = 0; - public const int PRIM_MATERIAL_METAL = 1; - public const int PRIM_MATERIAL_GLASS = 2; - public const int PRIM_MATERIAL_WOOD = 3; - public const int PRIM_MATERIAL_FLESH = 4; - public const int PRIM_MATERIAL_PLASTIC = 5; - public const int PRIM_MATERIAL_RUBBER = 6; - public const int PRIM_MATERIAL_LIGHT = 7; - public const int PRIM_SHINY_NONE = 0; - public const int PRIM_SHINY_LOW = 1; - public const int PRIM_SHINY_MEDIUM = 2; - public const int PRIM_SHINY_HIGH = 3; - public const int PRIM_BUMP_NONE = 0; - public const int PRIM_BUMP_BRIGHT = 1; - public const int PRIM_BUMP_DARK = 2; - public const int PRIM_BUMP_WOOD = 3; - public const int PRIM_BUMP_BARK = 4; - public const int PRIM_BUMP_BRICKS = 5; - public const int PRIM_BUMP_CHECKER = 6; - public const int PRIM_BUMP_CONCRETE = 7; - public const int PRIM_BUMP_TILE = 8; - public const int PRIM_BUMP_STONE = 9; - public const int PRIM_BUMP_DISKS = 10; - public const int PRIM_BUMP_GRAVEL = 11; - public const int PRIM_BUMP_BLOBS = 12; - public const int PRIM_BUMP_SIDING = 13; - public const int PRIM_BUMP_LARGETILE = 14; - public const int PRIM_BUMP_STUCCO = 15; - public const int PRIM_BUMP_SUCTION = 16; - public const int PRIM_BUMP_WEAVE = 17; - - public const int MASK_BASE = 0; - public const int MASK_OWNER = 1; - public const int MASK_GROUP = 2; - public const int MASK_EVERYONE = 3; - public const int MASK_NEXT = 4; - public const int PERM_TRANSFER = 8192; - public const int PERM_MODIFY = 16384; - public const int PERM_COPY = 32768; - public const int PERM_MOVE = 524288; - public const int PERM_ALL = 2147483647; - public const int PARCEL_MEDIA_COMMAND_STOP = 0; - public const int PARCEL_MEDIA_COMMAND_PAUSE = 1; - public const int PARCEL_MEDIA_COMMAND_PLAY = 2; - public const int PARCEL_MEDIA_COMMAND_LOOP = 3; - public const int PARCEL_MEDIA_COMMAND_TEXTURE = 4; - public const int PARCEL_MEDIA_COMMAND_URL = 5; - public const int PARCEL_MEDIA_COMMAND_TIME = 6; - public const int PARCEL_MEDIA_COMMAND_AGENT = 7; - public const int PARCEL_MEDIA_COMMAND_UNLOAD = 8; - public const int PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; - public const int PAY_HIDE = -1; - public const int PAY_DEFAULT = -2; - public const string NULL_KEY = "00000000-0000-0000-0000-000000000000"; - public const string EOF = "\n\n\n"; - public const double PI = 3.14159274f; - public const double TWO_PI = 6.28318548f; - public const double PI_BY_TWO = 1.57079637f; - public const double DEG_TO_RAD = 0.01745329238f; - public const double RAD_TO_DEG = 57.29578f; - public const double SQRT2 = 1.414213538f; - - // Can not be public const? - public vector ZERO_VECTOR = new vector(0, 0, 0); - public rotation ZERO_ROTATION = new rotation(0, 0, 0, 0); - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Threading; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; +using integer = System.Int32; +using key = System.String; +using vector = OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3; +using rotation = OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, IScript + { + // + // Included as base for any LSL-script that is compiled. + // Any function added here will be accessible to the LSL script. But it must also be added to "LSL_BuiltIn_Commands_Interface" in "OpenSim.Region.ScriptEngine.Common" class. + // + // Security note: This script will be running inside an restricted AppDomain. Currently AppDomain is not very restricted. + // + + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("LSL_BaseClass: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + //lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + //lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + public EventQueueManager.Queue_llDetectParams_Struct _llDetectParams; + EventQueueManager.Queue_llDetectParams_Struct IScript.llDetectParams + { + get { return _llDetectParams; } + set { _llDetectParams = value; } + } + + private Executor m_Exec; + + ExecutorBase IScript.Exec + { + get + { + if (m_Exec == null) + m_Exec = new Executor(this); + return m_Exec; + } + } + + + public LSL_BuiltIn_Commands_Interface m_LSL_Functions; + private string _Source = String.Empty; + public string Source + { + get + { + return _Source; + } + set { _Source = value; } + } + + + public LSL_BaseClass() + { + } + + public string State + { + get { return m_LSL_Functions.State; } + set { m_LSL_Functions.State = value; } + } + + + + public void Start(LSL_BuiltIn_Commands_Interface LSL_Functions) + { + m_LSL_Functions = LSL_Functions; + + //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called."); + + // Get this AppDomain's settings and display some of them. + AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation; + Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}", + ads.ApplicationName, + ads.ApplicationBase, + ads.ConfigurationFile + ); + + // Display the name of the calling AppDomain and the name + // of the second domain. + // NOTE: The application's thread has transitioned between + // AppDomains. + Console.WriteLine("Calling to '{0}'.", + Thread.GetDomain().FriendlyName + ); + + return; + } + + + + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + // They are only forwarders to LSL_BuiltIn_Commands.cs + // + public double llSin(double f) + { + return m_LSL_Functions.llSin(f); + } + + public double llCos(double f) + { + return m_LSL_Functions.llCos(f); + } + + public double llTan(double f) + { + return m_LSL_Functions.llTan(f); + } + + public double llAtan2(double x, double y) + { + return m_LSL_Functions.llAtan2(x, y); + } + + public double llSqrt(double f) + { + return m_LSL_Functions.llSqrt(f); + } + + public double llPow(double fbase, double fexponent) + { + return m_LSL_Functions.llPow(fbase, fexponent); + } + + public int llAbs(int i) + { + return m_LSL_Functions.llAbs(i); + } + + public double llFabs(double f) + { + return m_LSL_Functions.llFabs(f); + } + + public double llFrand(double mag) + { + return m_LSL_Functions.llFrand(mag); + } + + public int llFloor(double f) + { + return m_LSL_Functions.llFloor(f); + } + + public int llCeil(double f) + { + return m_LSL_Functions.llCeil(f); + } + + public int llRound(double f) + { + return m_LSL_Functions.llRound(f); + } + + public double llVecMag(vector v) + { + return m_LSL_Functions.llVecMag(v); + } + + public vector llVecNorm(vector v) + { + return m_LSL_Functions.llVecNorm(v); + } + + public double llVecDist(vector a, vector b) + { + return m_LSL_Functions.llVecDist(a, b); + } + + public vector llRot2Euler(rotation r) + { + return m_LSL_Functions.llRot2Euler(r); + } + + public rotation llEuler2Rot(vector v) + { + return m_LSL_Functions.llEuler2Rot(v); + } + + public rotation llAxes2Rot(vector fwd, vector left, vector up) + { + return m_LSL_Functions.llAxes2Rot(fwd, left, up); + } + + public vector llRot2Fwd(rotation r) + { + return m_LSL_Functions.llRot2Fwd(r); + } + + public vector llRot2Left(rotation r) + { + return m_LSL_Functions.llRot2Left(r); + } + + public vector llRot2Up(rotation r) + { + return m_LSL_Functions.llRot2Up(r); + } + + public rotation llRotBetween(vector start, vector end) + { + return m_LSL_Functions.llRotBetween(start, end); + } + + public void llWhisper(int channelID, string text) + { + m_LSL_Functions.llWhisper(channelID, text); + } + + public void llSay(int channelID, string text) + { + m_LSL_Functions.llSay(channelID, text); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llShout(int channelID, string text) + { + m_LSL_Functions.llShout(channelID, text); + } + + public int llListen(int channelID, string name, string ID, string msg) + { + return m_LSL_Functions.llListen(channelID, name, ID, msg); + } + + public void llListenControl(int number, int active) + { + m_LSL_Functions.llListenControl(number, active); + } + + public void llListenRemove(int number) + { + m_LSL_Functions.llListenRemove(number); + } + + public void llSensor(string name, string id, int type, double range, double arc) + { + m_LSL_Functions.llSensor(name, id, type, range, arc); + } + + public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) + { + m_LSL_Functions.llSensorRepeat(name, id, type, range, arc, rate); + } + + public void llSensorRemove() + { + m_LSL_Functions.llSensorRemove(); + } + + public string llDetectedName(int number) + { + return m_LSL_Functions.llDetectedName(number); + } + + public string llDetectedKey(int number) + { + return m_LSL_Functions.llDetectedKey(number); + } + + public string llDetectedOwner(int number) + { + return m_LSL_Functions.llDetectedOwner(number); + } + + public int llDetectedType(int number) + { + return m_LSL_Functions.llDetectedType(number); + } + + public vector llDetectedPos(int number) + { + return m_LSL_Functions.llDetectedPos(number); + } + + public vector llDetectedVel(int number) + { + return m_LSL_Functions.llDetectedVel(number); + } + + public vector llDetectedGrab(int number) + { + return m_LSL_Functions.llDetectedGrab(number); + } + + public rotation llDetectedRot(int number) + { + return m_LSL_Functions.llDetectedRot(number); + } + + public int llDetectedGroup(int number) + { + return m_LSL_Functions.llDetectedGroup(number); + } + + public int llDetectedLinkNumber(int number) + { + return m_LSL_Functions.llDetectedLinkNumber(number); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llDie() + { + m_LSL_Functions.llDie(); + } + + public double llGround(vector offset) + { + return m_LSL_Functions.llGround(offset); + } + + public double llCloud(vector offset) + { + return m_LSL_Functions.llCloud(offset); + } + + public vector llWind(vector offset) + { + return m_LSL_Functions.llWind(offset); + } + + public void llSetStatus(int status, int value) + { + m_LSL_Functions.llSetStatus(status, value); + } + + public int llGetStatus(int status) + { + return m_LSL_Functions.llGetStatus(status); + } + + public void llSetScale(vector scale) + { + m_LSL_Functions.llSetScale(scale); + } + + public vector llGetScale() + { + return m_LSL_Functions.llGetScale(); + } + + public void llSetColor(vector color, int face) + { + m_LSL_Functions.llSetColor(color, face); + } + + public double llGetAlpha(int face) + { + return m_LSL_Functions.llGetAlpha(face); + } + + public void llSetAlpha(double alpha, int face) + { + m_LSL_Functions.llSetAlpha(alpha, face); + } + + public vector llGetColor(int face) + { + return m_LSL_Functions.llGetColor(face); + } + + public void llSetTexture(string texture, int face) + { + m_LSL_Functions.llSetTexture(texture, face); + } + + public void llScaleTexture(double u, double v, int face) + { + m_LSL_Functions.llScaleTexture(u, v, face); + } + + public void llOffsetTexture(double u, double v, int face) + { + m_LSL_Functions.llOffsetTexture(u, v, face); + } + + public void llRotateTexture(double rotation, int face) + { + m_LSL_Functions.llRotateTexture(rotation, face); + } + + public string llGetTexture(int face) + { + return m_LSL_Functions.llGetTexture(face); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llSetPos(vector pos) + { + m_LSL_Functions.llSetPos(pos); + } + + public vector llGetPos() + { + return m_LSL_Functions.llGetPos(); + } + + public vector llGetLocalPos() + { + return m_LSL_Functions.llGetLocalPos(); + } + + public void llSetRot(rotation rot) + { + m_LSL_Functions.llSetRot(rot); + } + + public rotation llGetRot() + { + return m_LSL_Functions.llGetRot(); + } + + public rotation llGetLocalRot() + { + return m_LSL_Functions.llGetLocalRot(); + } + + public void llSetForce(vector force, int local) + { + m_LSL_Functions.llSetForce(force, local); + } + + public vector llGetForce() + { + return m_LSL_Functions.llGetForce(); + } + + public int llTarget(vector position, double range) + { + return m_LSL_Functions.llTarget(position, range); + } + + public void llTargetRemove(int number) + { + m_LSL_Functions.llTargetRemove(number); + } + + public int llRotTarget(rotation rot, double error) + { + return m_LSL_Functions.llRotTarget(rot, error); + } + + public void llRotTargetRemove(int number) + { + m_LSL_Functions.llRotTargetRemove(number); + } + + public void llMoveToTarget(vector target, double tau) + { + m_LSL_Functions.llMoveToTarget(target, tau); + } + + public void llStopMoveToTarget() + { + m_LSL_Functions.llStopMoveToTarget(); + } + + public void llApplyImpulse(vector force, int local) + { + m_LSL_Functions.llApplyImpulse(force, local); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llApplyRotationalImpulse(vector force, int local) + { + m_LSL_Functions.llApplyRotationalImpulse(force, local); + } + + public void llSetTorque(vector torque, int local) + { + m_LSL_Functions.llSetTorque(torque, local); + } + + public vector llGetTorque() + { + return m_LSL_Functions.llGetTorque(); + } + + public void llSetForceAndTorque(vector force, vector torque, int local) + { + m_LSL_Functions.llSetForceAndTorque(force, torque, local); + } + + public vector llGetVel() + { + return m_LSL_Functions.llGetVel(); + } + + public vector llGetAccel() + { + return m_LSL_Functions.llGetAccel(); + } + + public vector llGetOmega() + { + return m_LSL_Functions.llGetOmega(); + } + + public double llGetTimeOfDay() + { + return m_LSL_Functions.llGetTimeOfDay(); + } + + public double llGetWallclock() + { + return m_LSL_Functions.llGetWallclock(); + } + + public double llGetTime() + { + return m_LSL_Functions.llGetTime(); + } + + public void llResetTime() + { + m_LSL_Functions.llResetTime(); + } + + public double llGetAndResetTime() + { + return m_LSL_Functions.llGetAndResetTime(); + } + + public void llSound() + { + m_LSL_Functions.llSound(); + } + + public void llPlaySound(string sound, double volume) + { + m_LSL_Functions.llPlaySound(sound, volume); + } + + public void llLoopSound(string sound, double volume) + { + m_LSL_Functions.llLoopSound(sound, volume); + } + + public void llLoopSoundMaster(string sound, double volume) + { + m_LSL_Functions.llLoopSoundMaster(sound, volume); + } + + public void llLoopSoundSlave(string sound, double volume) + { + m_LSL_Functions.llLoopSoundSlave(sound, volume); + } + + public void llPlaySoundSlave(string sound, double volume) + { + m_LSL_Functions.llPlaySoundSlave(sound, volume); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llTriggerSound(string sound, double volume) + { + m_LSL_Functions.llTriggerSound(sound, volume); + } + + public void llStopSound() + { + m_LSL_Functions.llStopSound(); + } + + public void llPreloadSound(string sound) + { + m_LSL_Functions.llPreloadSound(sound); + } + + public string llGetSubString(string src, int start, int end) + { + return m_LSL_Functions.llGetSubString(src, start, end); + } + + public string llDeleteSubString(string src, int start, int end) + { + return m_LSL_Functions.llDeleteSubString(src, start, end); + } + + public string llInsertString(string dst, int position, string src) + { + return m_LSL_Functions.llInsertString(dst, position, src); + } + + public string llToUpper(string source) + { + return m_LSL_Functions.llToUpper(source); + } + + public string llToLower(string source) + { + return m_LSL_Functions.llToLower(source); + } + + public int llGiveMoney(string destination, int amount) + { + return m_LSL_Functions.llGiveMoney(destination, amount); + } + + public void llMakeExplosion() + { + m_LSL_Functions.llMakeExplosion(); + } + + public void llMakeFountain() + { + m_LSL_Functions.llMakeFountain(); + } + + public void llMakeSmoke() + { + m_LSL_Functions.llMakeSmoke(); + } + + public void llMakeFire() + { + m_LSL_Functions.llMakeFire(); + } + + public void llRezObject(string inventory, vector pos, rotation rot, int param) + { + m_LSL_Functions.llRezObject(inventory, pos, rot, param); + } + + public void llLookAt(vector target, double strength, double damping) + { + m_LSL_Functions.llLookAt(target, strength, damping); + } + + public void llStopLookAt() + { + m_LSL_Functions.llStopLookAt(); + } + + public void llSetTimerEvent(double sec) + { + m_LSL_Functions.llSetTimerEvent(sec); + } + + public void llSleep(double sec) + { + m_LSL_Functions.llSleep(sec); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public double llGetMass() + { + return m_LSL_Functions.llGetMass(); + } + + public void llCollisionFilter(string name, string id, int accept) + { + m_LSL_Functions.llCollisionFilter(name, id, accept); + } + + public void llTakeControls(int controls, int accept, int pass_on) + { + m_LSL_Functions.llTakeControls(controls, accept, pass_on); + } + + public void llReleaseControls() + { + m_LSL_Functions.llReleaseControls(); + } + + public void llAttachToAvatar(int attachment) + { + m_LSL_Functions.llAttachToAvatar(attachment); + } + + public void llDetachFromAvatar() + { + m_LSL_Functions.llDetachFromAvatar(); + } + + public void llTakeCamera() + { + m_LSL_Functions.llTakeCamera(); + } + + public void llReleaseCamera() + { + m_LSL_Functions.llReleaseCamera(); + } + + public string llGetOwner() + { + return m_LSL_Functions.llGetOwner(); + } + + public void llInstantMessage(string user, string message) + { + m_LSL_Functions.llInstantMessage(user, message); + } + + public void llEmail(string address, string subject, string message) + { + m_LSL_Functions.llEmail(address, subject, message); + } + + public void llGetNextEmail(string address, string subject) + { + m_LSL_Functions.llGetNextEmail(address, subject); + } + + public string llGetKey() + { + return m_LSL_Functions.llGetKey(); + } + + public void llSetBuoyancy(double buoyancy) + { + m_LSL_Functions.llSetBuoyancy(buoyancy); + } + + public void llSetHoverHeight(double height, int water, double tau) + { + m_LSL_Functions.llSetHoverHeight(height, water, tau); + } + + public void llStopHover() + { + m_LSL_Functions.llStopHover(); + } + + public void llMinEventDelay(double delay) + { + m_LSL_Functions.llMinEventDelay(delay); + } + + public void llSoundPreload() + { + m_LSL_Functions.llSoundPreload(); + } + + public void llRotLookAt(rotation target, double strength, double damping) + { + m_LSL_Functions.llRotLookAt(target, strength, damping); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llStringLength(string str) + { + return m_LSL_Functions.llStringLength(str); + } + + public void llStartAnimation(string anim) + { + m_LSL_Functions.llStartAnimation(anim); + } + + public void llStopAnimation(string anim) + { + m_LSL_Functions.llStopAnimation(anim); + } + + public void llPointAt() + { + m_LSL_Functions.llPointAt(); + } + + public void llStopPointAt() + { + m_LSL_Functions.llStopPointAt(); + } + + public void llTargetOmega(vector axis, double spinrate, double gain) + { + m_LSL_Functions.llTargetOmega(axis, spinrate, gain); + } + + public int llGetStartParameter() + { + return m_LSL_Functions.llGetStartParameter(); + } + + public void llGodLikeRezObject(string inventory, vector pos) + { + m_LSL_Functions.llGodLikeRezObject(inventory, pos); + } + + public void llRequestPermissions(string agent, int perm) + { + m_LSL_Functions.llRequestPermissions(agent, perm); + } + + public string llGetPermissionsKey() + { + return m_LSL_Functions.llGetPermissionsKey(); + } + + public int llGetPermissions() + { + return m_LSL_Functions.llGetPermissions(); + } + + public int llGetLinkNumber() + { + return m_LSL_Functions.llGetLinkNumber(); + } + + public void llSetLinkColor(int linknumber, vector color, int face) + { + m_LSL_Functions.llSetLinkColor(linknumber, color, face); + } + + public void llCreateLink(string target, int parent) + { + m_LSL_Functions.llCreateLink(target, parent); + } + + public void llBreakLink(int linknum) + { + m_LSL_Functions.llBreakLink(linknum); + } + + public void llBreakAllLinks() + { + m_LSL_Functions.llBreakAllLinks(); + } + + public string llGetLinkKey(int linknum) + { + return m_LSL_Functions.llGetLinkKey(linknum); + } + + public string llGetLinkName(int linknum) + { + return m_LSL_Functions.llGetLinkName(linknum); + } + + public int llGetInventoryNumber(int type) + { + return m_LSL_Functions.llGetInventoryNumber(type); + } + + public string llGetInventoryName(int type, int number) + { + return m_LSL_Functions.llGetInventoryName(type, number); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llSetScriptState(string name, int run) + { + m_LSL_Functions.llSetScriptState(name, run); + } + + public double llGetEnergy() + { + return m_LSL_Functions.llGetEnergy(); + } + + public void llGiveInventory(string destination, string inventory) + { + m_LSL_Functions.llGiveInventory(destination, inventory); + } + + public void llRemoveInventory(string item) + { + m_LSL_Functions.llRemoveInventory(item); + } + + public void llSetText(string text, vector color, double alpha) + { + m_LSL_Functions.llSetText(text, color, alpha); + } + + public double llWater(vector offset) + { + return m_LSL_Functions.llWater(offset); + } + + public void llPassTouches(int pass) + { + m_LSL_Functions.llPassTouches(pass); + } + + public string llRequestAgentData(string id, int data) + { + return m_LSL_Functions.llRequestAgentData(id, data); + } + + public string llRequestInventoryData(string name) + { + return m_LSL_Functions.llRequestInventoryData(name); + } + + public void llSetDamage(double damage) + { + m_LSL_Functions.llSetDamage(damage); + } + + public void llTeleportAgentHome(string agent) + { + m_LSL_Functions.llTeleportAgentHome(agent); + } + + public void llModifyLand(int action, int brush) + { + m_LSL_Functions.llModifyLand(action, brush); + } + + public void llCollisionSound(string impact_sound, double impact_volume) + { + m_LSL_Functions.llCollisionSound(impact_sound, impact_volume); + } + + public void llCollisionSprite(string impact_sprite) + { + m_LSL_Functions.llCollisionSprite(impact_sprite); + } + + public string llGetAnimation(string id) + { + return m_LSL_Functions.llGetAnimation(id); + } + + public void llResetScript() + { + m_LSL_Functions.llResetScript(); + } + + public void llMessageLinked(int linknum, int num, string str, string id) + { + m_LSL_Functions.llMessageLinked(linknum, num, str, id); + } + + public void llPushObject(string target, vector impulse, vector ang_impulse, int local) + { + m_LSL_Functions.llPushObject(target, impulse, ang_impulse, local); + } + + public void llPassCollisions(int pass) + { + m_LSL_Functions.llPassCollisions(pass); + } + + public string llGetScriptName() + { + return m_LSL_Functions.llGetScriptName(); + } + + public int llGetNumberOfSides() + { + return m_LSL_Functions.llGetNumberOfSides(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public rotation llAxisAngle2Rot(vector axis, double angle) + { + return m_LSL_Functions.llAxisAngle2Rot(axis, angle); + } + + public vector llRot2Axis(rotation rot) + { + return m_LSL_Functions.llRot2Axis(rot); + } + + public void llRot2Angle() + { + m_LSL_Functions.llRot2Angle(); + } + + public double llAcos(double val) + { + return m_LSL_Functions.llAcos(val); + } + + public double llAsin(double val) + { + return m_LSL_Functions.llAsin(val); + } + + public double llAngleBetween(rotation a, rotation b) + { + return m_LSL_Functions.llAngleBetween(a, b); + } + + public string llGetInventoryKey(string name) + { + return m_LSL_Functions.llGetInventoryKey(name); + } + + public void llAllowInventoryDrop(int add) + { + m_LSL_Functions.llAllowInventoryDrop(add); + } + + public vector llGetSunDirection() + { + return m_LSL_Functions.llGetSunDirection(); + } + + public vector llGetTextureOffset(int face) + { + return m_LSL_Functions.llGetTextureOffset(face); + } + + public vector llGetTextureScale(int side) + { + return m_LSL_Functions.llGetTextureScale(side); + } + + public double llGetTextureRot(int side) + { + return m_LSL_Functions.llGetTextureRot(side); + } + + public int llSubStringIndex(string source, string pattern) + { + return m_LSL_Functions.llSubStringIndex(source, pattern); + } + + public string llGetOwnerKey(string id) + { + return m_LSL_Functions.llGetOwnerKey(id); + } + + public vector llGetCenterOfMass() + { + return m_LSL_Functions.llGetCenterOfMass(); + } + + public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending) + { + return m_LSL_Functions.llListSort(src, stride, ascending); + } + + public int llGetListLength(LSL_Types.list src) + { + return m_LSL_Functions.llGetListLength(src); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llList2Integer(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Integer(src, index); + } + + public double osList2Double(LSL_Types.list src, int index) + { + return m_LSL_Functions.osList2Double(src, index); + } + + public string llList2String(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2String(src, index); + } + + public string llList2Key(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Key(src, index); + } + + public vector llList2Vector(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Vector(src, index); + } + + public rotation llList2Rot(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Rot(src, index); + } + + public LSL_Types.list llList2List(LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llList2List(src, start, end); + } + + public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llDeleteSubList(src, start, end); + } + + public int llGetListEntryType(LSL_Types.list src, int index) + { + return m_LSL_Functions.llGetListEntryType(src, index); + } + + public string llList2CSV(LSL_Types.list src) + { + return m_LSL_Functions.llList2CSV(src); + } + + public LSL_Types.list llCSV2List(string src) + { + return m_LSL_Functions.llCSV2List(src); + } + + public LSL_Types.list llListRandomize(LSL_Types.list src, int stride) + { + return m_LSL_Functions.llListRandomize(src, stride); + } + + public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride) + { + return m_LSL_Functions.llList2ListStrided(src, start, end, stride); + } + + public vector llGetRegionCorner() + { + return m_LSL_Functions.llGetRegionCorner(); + } + + public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start) + { + return m_LSL_Functions.llListInsertList(dest, src, start); + } + + public int llListFindList(LSL_Types.list src, LSL_Types.list test) + { + return m_LSL_Functions.llListFindList(src, test); + } + + public string llGetObjectName() + { + return m_LSL_Functions.llGetObjectName(); + } + + public void llSetObjectName(string name) + { + m_LSL_Functions.llSetObjectName(name); + } + + public string llGetDate() + { + return m_LSL_Functions.llGetDate(); + } + + public int llEdgeOfWorld(vector pos, vector dir) + { + return m_LSL_Functions.llEdgeOfWorld(pos, dir); + } + + public int llGetAgentInfo(string id) + { + return m_LSL_Functions.llGetAgentInfo(id); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llAdjustSoundVolume(double volume) + { + m_LSL_Functions.llAdjustSoundVolume(volume); + } + + public void llSetSoundQueueing(int queue) + { + m_LSL_Functions.llSetSoundQueueing(queue); + } + + public void llSetSoundRadius(double radius) + { + m_LSL_Functions.llSetSoundRadius(radius); + } + + public string llKey2Name(string id) + { + return m_LSL_Functions.llKey2Name(id); + } + + public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_LSL_Functions.llSetTextureAnim(mode, face, sizex, sizey, start, length, rate); + } + + public void llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) + { + m_LSL_Functions.llTriggerSoundLimited(sound, volume, top_north_east, bottom_south_west); + } + + public void llEjectFromLand(string pest) + { + m_LSL_Functions.llEjectFromLand(pest); + } + + public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers) + { + return m_LSL_Functions.llParseString2List(str,separators,spacers); + } + + public int llOverMyLand(string id) + { + return m_LSL_Functions.llOverMyLand(id); + } + + public string llGetLandOwnerAt(vector pos) + { + return m_LSL_Functions.llGetLandOwnerAt(pos); + } + + public string llGetNotecardLine(string name, int line) + { + return m_LSL_Functions.llGetNotecardLine(name, line); + } + + public vector llGetAgentSize(string id) + { + return m_LSL_Functions.llGetAgentSize(id); + } + + public int llSameGroup(string agent) + { + return m_LSL_Functions.llSameGroup(agent); + } + + public void llUnSit(string id) + { + m_LSL_Functions.llUnSit(id); + } + + public vector llGroundSlope(vector offset) + { + return m_LSL_Functions.llGroundSlope(offset); + } + + public vector llGroundNormal(vector offset) + { + return m_LSL_Functions.llGroundNormal(offset); + } + + public vector llGroundContour(vector offset) + { + return m_LSL_Functions.llGroundContour(offset); + } + + public int llGetAttached() + { + return m_LSL_Functions.llGetAttached(); + } + + public int llGetFreeMemory() + { + return m_LSL_Functions.llGetFreeMemory(); + } + + public string llGetRegionName() + { + return m_LSL_Functions.llGetRegionName(); + } + + public double llGetRegionTimeDilation() + { + return m_LSL_Functions.llGetRegionTimeDilation(); + } + + public double llGetRegionFPS() + { + return m_LSL_Functions.llGetRegionFPS(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llParticleSystem(LSL_Types.list rules) + { + m_LSL_Functions.llParticleSystem(rules); + } + + public void llGroundRepel(double height, int water, double tau) + { + m_LSL_Functions.llGroundRepel(height, water, tau); + } + + public void llGiveInventoryList() + { + m_LSL_Functions.llGiveInventoryList(); + } + + public void llSetVehicleType(int type) + { + m_LSL_Functions.llSetVehicleType(type); + } + + public void llSetVehicledoubleParam(int param, double value) + { + m_LSL_Functions.llSetVehicledoubleParam(param, value); + } + + public void llSetVehicleVectorParam(int param, vector vec) + { + m_LSL_Functions.llSetVehicleVectorParam(param, vec); + } + + public void llSetVehicleRotationParam(int param, rotation rot) + { + m_LSL_Functions.llSetVehicleRotationParam(param, rot); + } + + public void llSetVehicleFlags(int flags) + { + m_LSL_Functions.llSetVehicleFlags(flags); + } + + public void llRemoveVehicleFlags(int flags) + { + m_LSL_Functions.llRemoveVehicleFlags(flags); + } + + public void llSitTarget(vector offset, rotation rot) + { + m_LSL_Functions.llSitTarget(offset, rot); + } + + public string llAvatarOnSitTarget() + { + return m_LSL_Functions.llAvatarOnSitTarget(); + } + + public void llAddToLandPassList(string avatar, double hours) + { + m_LSL_Functions.llAddToLandPassList(avatar, hours); + } + + public void llSetTouchText(string text) + { + m_LSL_Functions.llSetTouchText(text); + } + + public void llSetSitText(string text) + { + m_LSL_Functions.llSetSitText(text); + } + + public void llSetCameraEyeOffset(vector offset) + { + m_LSL_Functions.llSetCameraEyeOffset(offset); + } + + public void llSetCameraAtOffset(vector offset) + { + m_LSL_Functions.llSetCameraAtOffset(offset); + } + + public string llDumpList2String(LSL_Types.list src, string seperator) + { + return m_LSL_Functions.llDumpList2String(src, seperator); + } + + public void llScriptDanger(vector pos) + { + m_LSL_Functions.llScriptDanger(pos); + } + + public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel) + { + m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); + } + + public void llVolumeDetect(int detect) + { + m_LSL_Functions.llVolumeDetect(detect); + } + + public void llResetOtherScript(string name) + { + m_LSL_Functions.llResetOtherScript(name); + } + + public int llGetScriptState(string name) + { + return m_LSL_Functions.llGetScriptState(name); + } + + public void llRemoteLoadScript() + { + m_LSL_Functions.llRemoteLoadScript(); + } + + public void llSetRemoteScriptAccessPin(int pin) + { + m_LSL_Functions.llSetRemoteScriptAccessPin(pin); + } + + public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) + { + m_LSL_Functions.llRemoteLoadScriptPin(target, name, pin, running, start_param); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llOpenRemoteDataChannel() + { + m_LSL_Functions.llOpenRemoteDataChannel(); + } + + public string llSendRemoteData(string channel, string dest, int idata, string sdata) + { + return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata); + } + + public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) + { + m_LSL_Functions.llRemoteDataReply(channel, message_id, sdata, idata); + } + + public void llCloseRemoteDataChannel(string channel) + { + m_LSL_Functions.llCloseRemoteDataChannel(channel); + } + + public string llMD5String(string src, int nonce) + { + return m_LSL_Functions.llMD5String(src, nonce); + } + + public void llSetPrimitiveParams(LSL_Types.list rules) + { + m_LSL_Functions.llSetPrimitiveParams(rules); + } + + public string llStringToBase64(string str) + { + return m_LSL_Functions.llStringToBase64(str); + } + + public string llBase64ToString(string str) + { + return m_LSL_Functions.llBase64ToString(str); + } + + public void llXorBase64Strings() + { + m_LSL_Functions.llXorBase64Strings(); + } + + public void llRemoteDataSetRegion() + { + m_LSL_Functions.llRemoteDataSetRegion(); + } + + public double llLog10(double val) + { + return m_LSL_Functions.llLog10(val); + } + + public double llLog(double val) + { + return m_LSL_Functions.llLog(val); + } + + public LSL_Types.list llGetAnimationList(string id) + { + return m_LSL_Functions.llGetAnimationList(id); + } + + public void llSetParcelMusicURL(string url) + { + m_LSL_Functions.llSetParcelMusicURL(url); + } + + public vector llGetRootPosition() + { + return m_LSL_Functions.llGetRootPosition(); + } + + public rotation llGetRootRotation() + { + return m_LSL_Functions.llGetRootRotation(); + } + + public string llGetObjectDesc() + { + return m_LSL_Functions.llGetObjectDesc(); + } + + public void llSetObjectDesc(string desc) + { + m_LSL_Functions.llSetObjectDesc(desc); + } + + public string llGetCreator() + { + return m_LSL_Functions.llGetCreator(); + } + + public string llGetTimestamp() + { + return m_LSL_Functions.llGetTimestamp(); + } + + public void llSetLinkAlpha(int linknumber, double alpha, int face) + { + m_LSL_Functions.llSetLinkAlpha(linknumber, alpha, face); + } + + public int llGetNumberOfPrims() + { + return m_LSL_Functions.llGetNumberOfPrims(); + } + + public string llGetNumberOfNotecardLines(string name) + { + return m_LSL_Functions.llGetNumberOfNotecardLines(name); + } + + public LSL_Types.list llGetBoundingBox(string obj) + { + return m_LSL_Functions.llGetBoundingBox(obj); + } + + public vector llGetGeometricCenter() + { + return m_LSL_Functions.llGetGeometricCenter(); + } + + public void llGetPrimitiveParams() + { + m_LSL_Functions.llGetPrimitiveParams(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public string llIntegerToBase64(int number) + { + return m_LSL_Functions.llIntegerToBase64(number); + } + + public int llBase64ToInteger(string str) + { + return m_LSL_Functions.llBase64ToInteger(str); + } + + public double llGetGMTclock() + { + return m_LSL_Functions.llGetGMTclock(); + } + + public string llGetSimulatorHostname() + { + return m_LSL_Functions.llGetSimulatorHostname(); + } + + public void llSetLocalRot(rotation rot) + { + m_LSL_Functions.llSetLocalRot(rot); + } + + public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers) + { + return m_LSL_Functions.llParseStringKeepNulls(src, seperators, spacers); + } + + public void llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, int param) + { + m_LSL_Functions.llRezAtRoot(inventory, position, velocity, rot, param); + } + + public int llGetObjectPermMask(int mask) + { + return m_LSL_Functions.llGetObjectPermMask(mask); + } + + public void llSetObjectPermMask(int mask, int value) + { + m_LSL_Functions.llSetObjectPermMask(mask, value); + } + + public void llGetInventoryPermMask(string item, int mask) + { + m_LSL_Functions.llGetInventoryPermMask(item, mask); + } + + public void llSetInventoryPermMask(string item, int mask, int value) + { + m_LSL_Functions.llSetInventoryPermMask(item, mask, value); + } + + public string llGetInventoryCreator(string item) + { + return m_LSL_Functions.llGetInventoryCreator(item); + } + + public void llOwnerSay(string msg) + { + m_LSL_Functions.llOwnerSay(msg); + } + + public void llRequestSimulatorData(string simulator, int data) + { + m_LSL_Functions.llRequestSimulatorData(simulator, data); + } + + public void llForceMouselook(int mouselook) + { + m_LSL_Functions.llForceMouselook(mouselook); + } + + public double llGetObjectMass(string id) + { + return m_LSL_Functions.llGetObjectMass(id); + } + + public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llListReplaceList(dest, src, start, end); + } + + public void llLoadURL(string avatar_id, string message, string url) + { + m_LSL_Functions.llLoadURL(avatar_id, message, url); + } + + public void llParcelMediaCommandList(LSL_Types.list commandList) + { + m_LSL_Functions.llParcelMediaCommandList(commandList); + } + + public void llParcelMediaQuery() + { + m_LSL_Functions.llParcelMediaQuery(); + } + + public int llModPow(int a, int b, int c) + { + return m_LSL_Functions.llModPow(a, b, c); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llGetInventoryType(string name) + { + return m_LSL_Functions.llGetInventoryType(name); + } + + public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) + { + m_LSL_Functions.llSetPayPrice(price, quick_pay_buttons); + } + + public vector llGetCameraPos() + { + return m_LSL_Functions.llGetCameraPos(); + } + + public rotation llGetCameraRot() + { + return m_LSL_Functions.llGetCameraRot(); + } + + public void llSetPrimURL() + { + m_LSL_Functions.llSetPrimURL(); + } + + public void llRefreshPrimURL() + { + m_LSL_Functions.llRefreshPrimURL(); + } + + public string llEscapeURL(string url) + { + return m_LSL_Functions.llEscapeURL(url); + } + + public string llUnescapeURL(string url) + { + return m_LSL_Functions.llUnescapeURL(url); + } + + public void llMapDestination(string simname, vector pos, vector look_at) + { + m_LSL_Functions.llMapDestination(simname, pos, look_at); + } + + public void llAddToLandBanList(string avatar, double hours) + { + m_LSL_Functions.llAddToLandBanList(avatar, hours); + } + + public void llRemoveFromLandPassList(string avatar) + { + m_LSL_Functions.llRemoveFromLandPassList(avatar); + } + + public void llRemoveFromLandBanList(string avatar) + { + m_LSL_Functions.llRemoveFromLandBanList(avatar); + } + + public void llSetCameraParams(LSL_Types.list rules) + { + m_LSL_Functions.llSetCameraParams(rules); + } + + public void llClearCameraParams() + { + m_LSL_Functions.llClearCameraParams(); + } + + public double llListStatistics(int operation, LSL_Types.list src) + { + return m_LSL_Functions.llListStatistics(operation, src); + } + + public int llGetUnixTime() + { + return m_LSL_Functions.llGetUnixTime(); + } + + public int llGetParcelFlags(vector pos) + { + return m_LSL_Functions.llGetParcelFlags(pos); + } + + public int llGetRegionFlags() + { + return m_LSL_Functions.llGetRegionFlags(); + } + + public string llXorBase64StringsCorrect(string str1, string str2) + { + return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2); + } + + public string llHTTPRequest(string url, LSL_Types.list parameters, string body) + { + return m_LSL_Functions.llHTTPRequest(url, parameters, body); + } + + public void llResetLandBanList() + { + m_LSL_Functions.llResetLandBanList(); + } + + public void llResetLandPassList() + { + m_LSL_Functions.llResetLandPassList(); + } + + public int llGetParcelPrimCount(vector pos, int category, int sim_wide) + { + return m_LSL_Functions.llGetParcelPrimCount(pos, category, sim_wide); + } + + public LSL_Types.list llGetParcelPrimOwners(vector pos) + { + return m_LSL_Functions.llGetParcelPrimOwners(pos); + } + + public int llGetObjectPrimCount(string object_id) + { + return m_LSL_Functions.llGetObjectPrimCount(object_id); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public int llGetParcelMaxPrims(vector pos, int sim_wide) + { + return m_LSL_Functions.llGetParcelMaxPrims(pos, sim_wide); + } + + public LSL_Types.list llGetParcelDetails(vector pos, LSL_Types.list param) + { + return m_LSL_Functions.llGetParcelDetails(pos, param); + } + + public string llStringTrim(string src, int type) + { + return m_LSL_Functions.llStringTrim(src, type); + } + + // + // OpenSim Functions + // + public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, + int timer) + { + return m_LSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer); + } + + public double osTerrainGetHeight(int x, int y) + { + return m_LSL_Functions.osTerrainGetHeight(x, y); + } + + public int osTerrainSetHeight(int x, int y, double val) + { + return m_LSL_Functions.osTerrainSetHeight(x, y, val); + } + + public int osRegionRestart(double seconds) + { + return m_LSL_Functions.osRegionRestart(seconds); + } + + public void osRegionNotice(string msg) + { + m_LSL_Functions.osRegionNotice(msg); + } + + public bool osConsoleCommand(string Command) + { + return m_LSL_Functions.osConsoleCommand(Command); + } + + public double llList2Float(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Float(src, index); + } + + // LSL CONSTANTS + public const int TRUE = 1; + public const int FALSE = 0; + public const int STATUS_PHYSICS = 1; + public const int STATUS_ROTATE_X = 2; + public const int STATUS_ROTATE_Y = 4; + public const int STATUS_ROTATE_Z = 8; + public const int STATUS_PHANTOM = 16; + public const int STATUS_SANDBOX = 32; + public const int STATUS_BLOCK_GRAB = 64; + public const int STATUS_DIE_AT_EDGE = 128; + public const int STATUS_RETURN_AT_EDGE = 256; + public const int STATUS_CAST_SHADOWS = 512; + public const int AGENT = 1; + public const int ACTIVE = 2; + public const int PASSIVE = 4; + public const int SCRIPTED = 8; + public const int CONTROL_FWD = 1; + public const int CONTROL_BACK = 2; + public const int CONTROL_LEFT = 4; + public const int CONTROL_RIGHT = 8; + public const int CONTROL_UP = 16; + public const int CONTROL_DOWN = 32; + public const int CONTROL_ROT_LEFT = 256; + public const int CONTROL_ROT_RIGHT = 512; + public const int CONTROL_LBUTTON = 268435456; + public const int CONTROL_ML_LBUTTON = 1073741824; + public const int PERMISSION_DEBIT = 2; + public const int PERMISSION_TAKE_CONTROLS = 4; + public const int PERMISSION_REMAP_CONTROLS = 8; + public const int PERMISSION_TRIGGER_ANIMATION = 16; + public const int PERMISSION_ATTACH = 32; + public const int PERMISSION_RELEASE_OWNERSHIP = 64; + public const int PERMISSION_CHANGE_LINKS = 128; + public const int PERMISSION_CHANGE_JOINTS = 256; + public const int PERMISSION_CHANGE_PERMISSIONS = 512; + public const int PERMISSION_TRACK_CAMERA = 1024; + public const int AGENT_FLYING = 1; + public const int AGENT_ATTACHMENTS = 2; + public const int AGENT_SCRIPTED = 4; + public const int AGENT_MOUSELOOK = 8; + public const int AGENT_SITTING = 16; + public const int AGENT_ON_OBJECT = 32; + public const int AGENT_AWAY = 64; + public const int AGENT_WALKING = 128; + public const int AGENT_IN_AIR = 256; + public const int AGENT_TYPING = 512; + public const int AGENT_CROUCHING = 1024; + public const int AGENT_BUSY = 2048; + public const int AGENT_ALWAYS_RUN = 4096; + public const int PSYS_PART_INTERP_COLOR_MASK = 1; + public const int PSYS_PART_INTERP_SCALE_MASK = 2; + public const int PSYS_PART_BOUNCE_MASK = 4; + public const int PSYS_PART_WIND_MASK = 8; + public const int PSYS_PART_FOLLOW_SRC_MASK = 16; + public const int PSYS_PART_FOLLOW_VELOCITY_MASK = 32; + public const int PSYS_PART_TARGET_POS_MASK = 64; + public const int PSYS_PART_TARGET_LINEAR_MASK = 128; + public const int PSYS_PART_EMISSIVE_MASK = 256; + public const int PSYS_PART_FLAGS = 0; + public const int PSYS_PART_START_COLOR = 1; + public const int PSYS_PART_START_ALPHA = 2; + public const int PSYS_PART_END_COLOR = 3; + public const int PSYS_PART_END_ALPHA = 4; + public const int PSYS_PART_START_SCALE = 5; + public const int PSYS_PART_END_SCALE = 6; + public const int PSYS_PART_MAX_AGE = 7; + public const int PSYS_SRC_ACCEL = 8; + public const int PSYS_SRC_PATTERN = 9; + public const int PSYS_SRC_INNERANGLE = 10; + public const int PSYS_SRC_OUTERANGLE = 11; + public const int PSYS_SRC_TEXTURE = 12; + public const int PSYS_SRC_BURST_RATE = 13; + public const int PSYS_SRC_BURST_PART_COUNT = 15; + public const int PSYS_SRC_BURST_RADIUS = 16; + public const int PSYS_SRC_BURST_SPEED_MIN = 17; + public const int PSYS_SRC_BURST_SPEED_MAX = 18; + public const int PSYS_SRC_MAX_AGE = 19; + public const int PSYS_SRC_TARGET_KEY = 20; + public const int PSYS_SRC_OMEGA = 21; + public const int PSYS_SRC_ANGLE_BEGIN = 22; + public const int PSYS_SRC_ANGLE_END = 23; + public const int PSYS_SRC_PATTERN_DROP = 1; + public const int PSYS_SRC_PATTERN_EXPLODE = 2; + public const int PSYS_SRC_PATTERN_ANGLE = 4; + public const int PSYS_SRC_PATTERN_ANGLE_CONE = 8; + public const int PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY = 16; + public const int VEHICLE_TYPE_NONE = 0; + public const int VEHICLE_TYPE_SLED = 1; + public const int VEHICLE_TYPE_CAR = 2; + public const int VEHICLE_TYPE_BOAT = 3; + public const int VEHICLE_TYPE_AIRPLANE = 4; + public const int VEHICLE_TYPE_BALLOON = 5; + public const int VEHICLE_LINEAR_FRICTION_TIMESCALE = 16; + public const int VEHICLE_ANGULAR_FRICTION_TIMESCALE = 17; + public const int VEHICLE_LINEAR_MOTOR_DIRECTION = 18; + public const int VEHICLE_LINEAR_MOTOR_OFFSET = 20; + public const int VEHICLE_ANGULAR_MOTOR_DIRECTION = 19; + public const int VEHICLE_HOVER_HEIGHT = 24; + public const int VEHICLE_HOVER_EFFICIENCY = 25; + public const int VEHICLE_HOVER_TIMESCALE = 26; + public const int VEHICLE_BUOYANCY = 27; + public const int VEHICLE_LINEAR_DEFLECTION_EFFICIENCY = 28; + public const int VEHICLE_LINEAR_DEFLECTION_TIMESCALE = 29; + public const int VEHICLE_LINEAR_MOTOR_TIMESCALE = 30; + public const int VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE = 31; + public const int VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY = 32; + public const int VEHICLE_ANGULAR_DEFLECTION_TIMESCALE = 33; + public const int VEHICLE_ANGULAR_MOTOR_TIMESCALE = 34; + public const int VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE = 35; + public const int VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY = 36; + public const int VEHICLE_VERTICAL_ATTRACTION_TIMESCALE = 37; + public const int VEHICLE_BANKING_EFFICIENCY = 38; + public const int VEHICLE_BANKING_MIX = 39; + public const int VEHICLE_BANKING_TIMESCALE = 40; + public const int VEHICLE_REFERENCE_FRAME = 44; + public const int VEHICLE_FLAG_NO_DEFLECTION_UP = 1; + public const int VEHICLE_FLAG_LIMIT_ROLL_ONLY = 2; + public const int VEHICLE_FLAG_HOVER_WATER_ONLY = 4; + public const int VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 8; + public const int VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT = 16; + public const int VEHICLE_FLAG_HOVER_UP_ONLY = 32; + public const int VEHICLE_FLAG_LIMIT_MOTOR_UP = 64; + public const int VEHICLE_FLAG_MOUSELOOK_STEER = 128; + public const int VEHICLE_FLAG_MOUSELOOK_BANK = 256; + public const int VEHICLE_FLAG_CAMERA_DECOUPLED = 512; + public const int INVENTORY_ALL = -1; + public const int INVENTORY_NONE = -1; + public const int INVENTORY_TEXTURE = 0; + public const int INVENTORY_SOUND = 1; + public const int INVENTORY_LANDMARK = 3; + public const int INVENTORY_CLOTHING = 5; + public const int INVENTORY_OBJECT = 6; + public const int INVENTORY_NOTECARD = 7; + public const int INVENTORY_SCRIPT = 10; + public const int INVENTORY_BODYPART = 13; + public const int INVENTORY_ANIMATION = 20; + public const int INVENTORY_GESTURE = 21; + public const int ATTACH_CHEST = 1; + public const int ATTACH_HEAD = 2; + public const int ATTACH_LSHOULDER = 3; + public const int ATTACH_RSHOULDER = 4; + public const int ATTACH_LHAND = 5; + public const int ATTACH_RHAND = 6; + public const int ATTACH_LFOOT = 7; + public const int ATTACH_RFOOT = 8; + public const int ATTACH_BACK = 9; + public const int ATTACH_PELVIS = 10; + public const int ATTACH_MOUTH = 11; + public const int ATTACH_CHIN = 12; + public const int ATTACH_LEAR = 13; + public const int ATTACH_REAR = 14; + public const int ATTACH_LEYE = 15; + public const int ATTACH_REYE = 16; + public const int ATTACH_NOSE = 17; + public const int ATTACH_RUARM = 18; + public const int ATTACH_RLARM = 19; + public const int ATTACH_LUARM = 20; + public const int ATTACH_LLARM = 21; + public const int ATTACH_RHIP = 22; + public const int ATTACH_RULEG = 23; + public const int ATTACH_RLLEG = 24; + public const int ATTACH_LHIP = 25; + public const int ATTACH_LULEG = 26; + public const int ATTACH_LLLEG = 27; + public const int ATTACH_BELLY = 28; + public const int ATTACH_RPEC = 29; + public const int ATTACH_LPEC = 30; + public const int LAND_LEVEL = 0; + public const int LAND_RAISE = 1; + public const int LAND_LOWER = 2; + public const int LAND_SMOOTH = 3; + public const int LAND_NOISE = 4; + public const int LAND_REVERT = 5; + public const int LAND_SMALL_BRUSH = 1; + public const int LAND_MEDIUM_BRUSH = 2; + public const int LAND_LARGE_BRUSH = 3; + public const int DATA_ONLINE = 1; + public const int DATA_NAME = 2; + public const int DATA_BORN = 3; + public const int DATA_RATING = 4; + public const int DATA_SIM_POS = 5; + public const int DATA_SIM_STATUS = 6; + public const int DATA_SIM_RATING = 7; + public const int ANIM_ON = 1; + public const int LOOP = 2; + public const int REVERSE = 4; + public const int PING_PONG = 8; + public const int SMOOTH = 16; + public const int ROTATE = 32; + public const int SCALE = 64; + public const int ALL_SIDES = -1; + public const int LINK_SET = -1; + public const int LINK_ROOT = 1; + public const int LINK_ALL_OTHERS = -2; + public const int LINK_ALL_CHILDREN = -3; + public const int LINK_THIS = -4; + public const int CHANGED_INVENTORY = 1; + public const int CHANGED_COLOR = 2; + public const int CHANGED_SHAPE = 4; + public const int CHANGED_SCALE = 8; + public const int CHANGED_TEXTURE = 16; + public const int CHANGED_LINK = 32; + public const int CHANGED_ALLOWED_DROP = 64; + public const int CHANGED_OWNER = 128; + public const int TYPE_INVALID = 0; + public const int TYPE_INTEGER = 1; + public const int TYPE_double = 2; + public const int TYPE_STRING = 3; + public const int TYPE_KEY = 4; + public const int TYPE_VECTOR = 5; + public const int TYPE_ROTATION = 6; + public const int REMOTE_DATA_CHANNEL = 1; + public const int REMOTE_DATA_REQUEST = 2; + public const int REMOTE_DATA_REPLY = 3; + public const int HTTP_METHOD = 0; + public const int HTTP_MIMETYPE = 1; + public const int HTTP_BODY_MAXLENGTH = 2; + public const int HTTP_VERIFY_CERT = 3; + + public const int PRIM_MATERIAL = 2; + public const int PRIM_PHYSICS = 3; + public const int PRIM_TEMP_ON_REZ = 4; + public const int PRIM_PHANTOM = 5; + public const int PRIM_POSITION = 6; + public const int PRIM_SIZE = 7; + public const int PRIM_ROTATION = 8; + public const int PRIM_TYPE = 9; + public const int PRIM_TEXTURE = 17; + public const int PRIM_COLOR = 18; + public const int PRIM_BUMP_SHINY = 19; + public const int PRIM_FULLBRIGHT = 20; + public const int PRIM_FLEXIBLE = 21; + public const int PRIM_TEXGEN = 22; + public const int PRIM_CAST_SHADOWS = 24; // Not implemented, here for completeness sake + public const int PRIM_POINT_LIGHT = 23; // Huh? + public const int PRIM_TEXGEN_DEFAULT = 0; + public const int PRIM_TEXGEN_PLANAR = 1; + public const int PRIM_TYPE_BOX = 0; + public const int PRIM_TYPE_CYLINDER = 1; + public const int PRIM_TYPE_PRISM = 2; + public const int PRIM_TYPE_SPHERE = 3; + public const int PRIM_TYPE_TORUS = 4; + public const int PRIM_TYPE_TUBE = 5; + public const int PRIM_TYPE_RING = 6; + public const int PRIM_TYPE_SCULPT = 7; + public const int PRIM_HOLE_DEFAULT = 0; + public const int PRIM_HOLE_CIRCLE = 16; + public const int PRIM_HOLE_SQUARE = 32; + public const int PRIM_HOLE_TRIANGLE = 48; + public const int PRIM_MATERIAL_STONE = 0; + public const int PRIM_MATERIAL_METAL = 1; + public const int PRIM_MATERIAL_GLASS = 2; + public const int PRIM_MATERIAL_WOOD = 3; + public const int PRIM_MATERIAL_FLESH = 4; + public const int PRIM_MATERIAL_PLASTIC = 5; + public const int PRIM_MATERIAL_RUBBER = 6; + public const int PRIM_MATERIAL_LIGHT = 7; + public const int PRIM_SHINY_NONE = 0; + public const int PRIM_SHINY_LOW = 1; + public const int PRIM_SHINY_MEDIUM = 2; + public const int PRIM_SHINY_HIGH = 3; + public const int PRIM_BUMP_NONE = 0; + public const int PRIM_BUMP_BRIGHT = 1; + public const int PRIM_BUMP_DARK = 2; + public const int PRIM_BUMP_WOOD = 3; + public const int PRIM_BUMP_BARK = 4; + public const int PRIM_BUMP_BRICKS = 5; + public const int PRIM_BUMP_CHECKER = 6; + public const int PRIM_BUMP_CONCRETE = 7; + public const int PRIM_BUMP_TILE = 8; + public const int PRIM_BUMP_STONE = 9; + public const int PRIM_BUMP_DISKS = 10; + public const int PRIM_BUMP_GRAVEL = 11; + public const int PRIM_BUMP_BLOBS = 12; + public const int PRIM_BUMP_SIDING = 13; + public const int PRIM_BUMP_LARGETILE = 14; + public const int PRIM_BUMP_STUCCO = 15; + public const int PRIM_BUMP_SUCTION = 16; + public const int PRIM_BUMP_WEAVE = 17; + + public const int PRIM_SCULPT_TYPE_SPHERE = 1; + public const int PRIM_SCULPT_TYPE_TORUS = 2; + public const int PRIM_SCULPT_TYPE_PLANE = 3; + public const int PRIM_SCULPT_TYPE_CYLINDER = 4; + + public const int MASK_BASE = 0; + public const int MASK_OWNER = 1; + public const int MASK_GROUP = 2; + public const int MASK_EVERYONE = 3; + public const int MASK_NEXT = 4; + public const int PERM_TRANSFER = 8192; + public const int PERM_MODIFY = 16384; + public const int PERM_COPY = 32768; + public const int PERM_MOVE = 524288; + public const int PERM_ALL = 2147483647; + public const int PARCEL_MEDIA_COMMAND_STOP = 0; + public const int PARCEL_MEDIA_COMMAND_PAUSE = 1; + public const int PARCEL_MEDIA_COMMAND_PLAY = 2; + public const int PARCEL_MEDIA_COMMAND_LOOP = 3; + public const int PARCEL_MEDIA_COMMAND_TEXTURE = 4; + public const int PARCEL_MEDIA_COMMAND_URL = 5; + public const int PARCEL_MEDIA_COMMAND_TIME = 6; + public const int PARCEL_MEDIA_COMMAND_AGENT = 7; + public const int PARCEL_MEDIA_COMMAND_UNLOAD = 8; + public const int PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; + public const int PAY_HIDE = -1; + public const int PAY_DEFAULT = -2; + public const string NULL_KEY = "00000000-0000-0000-0000-000000000000"; + public const string EOF = "\n\n\n"; + public const double PI = 3.14159274f; + public const double TWO_PI = 6.28318548f; + public const double PI_BY_TWO = 1.57079637f; + public const double DEG_TO_RAD = 0.01745329238f; + public const double RAD_TO_DEG = 57.29578f; + public const double SQRT2 = 1.414213538f; + public const int STRING_TRIM_HEAD = 1; + public const int STRING_TRIM_TAIL = 2; + public const int STRING_TRIM = 3; + public const int LIST_STAT_RANGE = 0; + public const int LIST_STAT_MIN = 1; + public const int LIST_STAT_MAX = 2; + public const int LIST_STAT_MEAN = 3; + public const int LIST_STAT_MEDIAN = 4; + public const int LIST_STAT_STD_DEV = 5; + public const int LIST_STAT_SUM = 6; + public const int LIST_STAT_SUM_SQUARES = 7; + public const int LIST_STAT_NUM_COUNT = 8; + public const int LIST_STAT_GEOMETRIC_MEAN = 9; + public const int LIST_STAT_HARMONIC_MEAN = 100; + // Can not be public const? + public vector ZERO_VECTOR = new vector(0.0, 0.0, 0.0); + public rotation ZERO_ROTATION = new rotation(0.0, 0, 0.0, 1.0); + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs similarity index 72% rename from OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs rename to OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs index 61a62e6eda..b91751d92a 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs @@ -1,3072 +1,3699 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Runtime.Remoting.Lifetime; -using System.Text; -using System.Threading; -using Axiom.Math; -using libsecondlife; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; -using OpenSim.Region.ScriptEngine.Common; -using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler -{ - // - // !!!IMPORTANT!!! - // - // REMEMBER TO UPDATE http://opensimulator.org/wiki/LlFunction_implementation_status - // - - // Notes: - // * If any function here needs to execute a LSL event in the script, use instance of "EventQueueManager" in "ScriptEngine". - // * If any function here needs to do some more advanced stuff like waiting for IO callbacks or similar that takes a long time then use "llSetTimerEvent" function as example. - // There is a class called "LSLLongCmdHandler" that is used for long LSL commands. - - - /// - /// Contains all LSL ll-functions. This class will be in Default AppDomain. - /// - public class LSL_BuiltIn_Commands : MarshalByRefObject, LSL_BuiltIn_Commands_Interface - { - private ASCIIEncoding enc = new ASCIIEncoding(); - protected ScriptEngine m_ScriptEngine; - protected SceneObjectPart m_host; - protected uint m_localID; - protected LLUUID m_itemID; - private bool throwErrorOnNotImplemented = true; - - /// - /// - /// - /// - /// - /// Item's local id - /// Item's LLUUID - public LSL_BuiltIn_Commands(ScriptEngine ScriptEngine, SceneObjectPart host, uint localID, LLUUID itemID) - { - m_ScriptEngine = ScriptEngine; - m_host = host; - m_localID = localID; - m_itemID = itemID; - - //MainLog.Instance.Notice("ScriptEngine", "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]"); - } - - private DateTime m_timer = DateTime.Now; - private string m_state = "default"; - - public string State() - { - return m_state; - } - - // Object never expires - public override Object InitializeLifetimeService() - { - //Console.WriteLine("LSL_BuiltIn_Commands: InitializeLifetimeService()"); - // return null; - ILease lease = (ILease)base.InitializeLifetimeService(); - - if (lease.CurrentState == LeaseState.Initial) - { - lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); - // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); - // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); - } - return lease; - } - - public Scene World - { - get { return m_ScriptEngine.World; } - } - - //These are the implementations of the various ll-functions used by the LSL scripts. - //starting out, we use the System.Math library for trig functions. - ckrinke 8-14-07 - public double llSin(double f) - { - - return (double)Math.Sin(f); - } - - public double llCos(double f) - { - return (double)Math.Cos(f); - } - - public double llTan(double f) - { - return (double)Math.Tan(f); - } - - public double llAtan2(double x, double y) - { - return (double)Math.Atan2(y, x); - } - - public double llSqrt(double f) - { - return (double)Math.Sqrt(f); - } - - public double llPow(double fbase, double fexponent) - { - return (double)Math.Pow(fbase, fexponent); - } - - public int llAbs(int i) - { - return (int)Math.Abs(i); - } - - public double llFabs(double f) - { - return (double)Math.Abs(f); - } - - public double llFrand(double mag) - { - lock (Util.RandomClass) - { - return Util.RandomClass.NextDouble() * mag; - } - } - - public int llFloor(double f) - { - return (int)Math.Floor(f); - } - - public int llCeil(double f) - { - return (int)Math.Ceiling(f); - } - - public int llRound(double f) - { - return (int)Math.Round(f, 0); - } - - //This next group are vector operations involving squaring and square root. ckrinke - public double llVecMag(LSL_Types.Vector3 v) - { - return (v.x * v.x + v.y * v.y + v.z * v.z); - } - - public LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v) - { - double mag = v.x * v.x + v.y * v.y + v.z * v.z; - LSL_Types.Vector3 nor = new LSL_Types.Vector3(); - nor.x = v.x / mag; - nor.y = v.y / mag; - nor.z = v.z / mag; - return nor; - } - - public double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b) - { - 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); - } - - //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke - public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) - { - //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke - LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); - double m = (t.x + t.y + t.z + t.s); - if (m == 0) return new LSL_Types.Vector3(); - double n = 2 * (r.y * r.s + r.x * r.z); - double p = m * m - n * n; - if (p > 0) - return new LSL_Types.Vector3(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)), - Math.Atan2(n, Math.Sqrt(p)), - Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))); - else if (n > 0) - return new LSL_Types.Vector3(0.0, Math.PI / 2, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); - else - return new LSL_Types.Vector3(0.0, -Math.PI / 2, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); - } - - public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) - { - //this comes from from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions but is incomplete as of 8/19/07 - float err = 0.00001f; - double ax = Math.Sin(v.x / 2); - double aw = Math.Cos(v.x / 2); - double by = Math.Sin(v.y / 2); - double bw = Math.Cos(v.y / 2); - double cz = Math.Sin(v.z / 2); - double cw = Math.Cos(v.z / 2); - LSL_Types.Quaternion a1 = new LSL_Types.Quaternion(0.0, 0.0, cz, cw); - LSL_Types.Quaternion a2 = new LSL_Types.Quaternion(0.0, by, 0.0, bw); - LSL_Types.Quaternion a3 = new LSL_Types.Quaternion(ax, 0.0, 0.0, aw); - LSL_Types.Quaternion a = (a1 * a2) * a3; - //This multiplication doesnt compile, yet. a = a1 * a2 * a3; - LSL_Types.Quaternion b = new LSL_Types.Quaternion(ax * bw * cw + aw * by * cz, - aw * by * cw - ax * bw * cz, aw * bw * cz + ax * by * cw, - aw * bw * cw - ax * by * cz); - LSL_Types.Quaternion c = new LSL_Types.Quaternion(); - //This addition doesnt compile yet c = a + b; - LSL_Types.Quaternion d = new LSL_Types.Quaternion(); - //This addition doesnt compile yet d = a - b; - if ((Math.Abs(c.x) > err && Math.Abs(d.x) > err) || - (Math.Abs(c.y) > err && Math.Abs(d.y) > err) || - (Math.Abs(c.z) > err && Math.Abs(d.z) > err) || - (Math.Abs(c.s) > err && Math.Abs(d.s) > err)) - { - return b; - //return a new Quaternion that is null until I figure this out - // return b; - // return a; - } - return a; - } - - public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) - { - return new LSL_Types.Quaternion(); - } - - public LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r) - { - return (new LSL_Types.Vector3(1, 0, 0) * r); - } - - public LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r) - { - return (new LSL_Types.Vector3(0, 1, 0) * r); - } - - public LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r) - { - return (new LSL_Types.Vector3(0, 0, 1) * r); - } - public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 a, LSL_Types.Vector3 b) - { - //A and B should both be normalized - - double dotProduct = LSL_Types.Vector3.Dot(a, b); - LSL_Types.Vector3 crossProduct = LSL_Types.Vector3.Cross(a, b); - double magProduct = LSL_Types.Vector3.Mag(a) * LSL_Types.Vector3.Mag(b); - double angle = Math.Acos(dotProduct / magProduct); - LSL_Types.Vector3 axis = LSL_Types.Vector3.Norm(crossProduct); - double s = Math.Sin(angle / 2); - - return new LSL_Types.Quaternion(axis.x * s, axis.y * s, axis.z * s, (float)Math.Cos(angle / 2)); - } - public void llWhisper(int channelID, string text) - { - World.SimChat(Helpers.StringToField(text), - ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); - - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Whisper, channelID, m_host.Name, text); - } - - public void llSay(int channelID, string text) - { - World.SimChat(Helpers.StringToField(text), - ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); - - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Say, channelID, m_host.Name, text); - } - - public void llShout(int channelID, string text) - { - World.SimChat(Helpers.StringToField(text), - ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); - - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Shout, channelID, m_host.Name, text); - } - - public int llListen(int channelID, string name, string ID, string msg) - { - if (ID == "") - { - ID = LLUUID.Zero.ToString(); - } - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, ID, msg); - } - - public void llListenControl(int number, int active) - { - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.ListenControl(number, active); - } - - public void llListenRemove(int number) - { - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.ListenRemove(number); - } - - public void llSensor(string name, string id, int type, double range, double arc) - { - NotImplemented("llSensor"); - return; - } - - public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) - { - NotImplemented("llSensorRepeat"); - return; - } - - public void llSensorRemove() - { - NotImplemented("llSensorRemove"); - return; - } - - public string llDetectedName(int number) - { - NotImplemented("llDetectedName"); - return ""; - } - - public string llDetectedKey(int number) - { - NotImplemented("llDetectedKey"); - return ""; - } - - public string llDetectedOwner(int number) - { - NotImplemented("llDetectedOwner"); - return ""; - } - - public int llDetectedType(int number) - { - NotImplemented("llDetectedType"); - return 0; - } - - public LSL_Types.Vector3 llDetectedPos(int number) - { - NotImplemented("llDetectedPos"); - return new LSL_Types.Vector3(); - } - - public LSL_Types.Vector3 llDetectedVel(int number) - { - NotImplemented("llDetectedVel"); - return new LSL_Types.Vector3(); - } - - public LSL_Types.Vector3 llDetectedGrab(int number) - { - NotImplemented("llDetectedGrab"); - return new LSL_Types.Vector3(); - } - - public LSL_Types.Quaternion llDetectedRot(int number) - { - NotImplemented("llDetectedRot"); - return new LSL_Types.Quaternion(); - } - - public int llDetectedGroup(int number) - { - NotImplemented("llDetectedGroup"); - return 0; - } - - public int llDetectedLinkNumber(int number) - { - NotImplemented("llDetectedLinkNumber"); - return 0; - } - - public void llDie() - { - World.DeleteSceneObjectGroup(m_host.ParentGroup); - return; - } - - public double llGround(LSL_Types.Vector3 offset) - { - int x = (int)(m_host.AbsolutePosition.X + offset.x); - int y = (int)(m_host.AbsolutePosition.Y + offset.y); - return World.GetLandHeight(x, y); - } - - public double llCloud(LSL_Types.Vector3 offset) - { - NotImplemented("llCloud"); - return 0; - } - - public LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset) - { - NotImplemented("llWind"); - return new LSL_Types.Vector3(); - } - - public void llSetStatus(int status, int value) - { - NotImplemented("llSetStatus"); - return; - } - - public int llGetStatus(int status) - { - NotImplemented("llGetStatus"); - return 0; - } - - public void llSetScale(LSL_Types.Vector3 scale) - { - // TODO: this needs to trigger a persistance save as well - LLVector3 tmp = m_host.Scale; - tmp.X = (float)scale.x; - tmp.Y = (float)scale.y; - tmp.Z = (float)scale.z; - m_host.Scale = tmp; - m_host.SendFullUpdateToAllClients(); - return; - } - - public LSL_Types.Vector3 llGetScale() - { - return new LSL_Types.Vector3(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); - } - - public void llSetColor(LSL_Types.Vector3 color, int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - LLColor texcolor; - if (face > -1) - { - texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.FaceTextures[face].RGBA = texcolor; - m_host.UpdateTexture(tex); - return; - } - else if (face == -1) - { - for (uint i = 0; i < 32; i++) - { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.FaceTextures[i].RGBA = texcolor; - } - texcolor = tex.DefaultTexture.RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.DefaultTexture.RGBA = texcolor; - } - m_host.UpdateTexture(tex); - return; - } - NotImplemented("llSetColor"); - return; - } - - public double llGetAlpha(int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color - { - return (double)((tex.DefaultTexture.RGBA.A * 255) / 255); - } - if (face > -1) - { - return (double)((tex.GetFace((uint)face).RGBA.A * 255) / 255); - } - return 0; - } - - public void llSetAlpha(double alpha, int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - LLColor texcolor; - if (face > -1) - { - texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.FaceTextures[face].RGBA = texcolor; - m_host.UpdateTexture(tex); - return; - } - else if (face == -1) - { - for (int i = 0; i < 32; i++) - { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.FaceTextures[i].RGBA = texcolor; - } - } - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.DefaultTexture.RGBA = texcolor; - m_host.UpdateTexture(tex); - return; - } - NotImplemented("llSetAlpha"); - return; - } - - public LSL_Types.Vector3 llGetColor(int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - LLColor texcolor; - LSL_Types.Vector3 rgb; - if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color - { - texcolor = tex.DefaultTexture.RGBA; - rgb.x = (255 - (texcolor.R * 255)) / 255; - rgb.y = (255 - (texcolor.G * 255)) / 255; - rgb.z = (255 - (texcolor.B * 255)) / 255; - return rgb; - } - if (face > -1) - { - texcolor = tex.GetFace((uint)face).RGBA; - rgb.x = (255 - (texcolor.R * 255)) / 255; - rgb.y = (255 - (texcolor.G * 255)) / 255; - rgb.z = (255 - (texcolor.B * 255)) / 255; - return rgb; - } - NotImplemented("llGetColor"); - return new LSL_Types.Vector3(); - } - - public void llSetTexture(string texture, int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - - if (face > -1) - { - LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); - texface.TextureID = new LLUUID(texture); - tex.FaceTextures[face] = texface; - m_host.UpdateTexture(tex); - return; - } - else if (face == -1) - { - for (uint i = 0; i < 32; i++) - { - if (tex.FaceTextures[i] != null) - { - tex.FaceTextures[i].TextureID = new LLUUID(texture); - } - } - tex.DefaultTexture.TextureID = new LLUUID(texture); - m_host.UpdateTexture(tex); - return; - } - NotImplemented("llSetTexture"); - return; - } - - public void llScaleTexture(double u, double v, int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - if (face > -1) - { - LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); - texface.RepeatU = (float)u; - texface.RepeatV = (float)v; - tex.FaceTextures[face] = texface; - m_host.UpdateTexture(tex); - return; - } - if (face == -1) - { - for (int i = 0; i < 32; 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; - m_host.UpdateTexture(tex); - return; - } - NotImplemented("llScaleTexture"); - return; - } - - public void llOffsetTexture(double u, double v, int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - if (face > -1) - { - LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); - texface.OffsetU = (float)u; - texface.OffsetV = (float)v; - tex.FaceTextures[face] = texface; - m_host.UpdateTexture(tex); - return; - } - if (face == -1) - { - for (int i = 0; i < 32; 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; - m_host.UpdateTexture(tex); - return; - } - NotImplemented("llOffsetTexture"); - return; - } - - public void llRotateTexture(double rotation, int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - if (face > -1) - { - LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); - texface.Rotation = (float)rotation; - tex.FaceTextures[face] = texface; - m_host.UpdateTexture(tex); - return; - } - if (face == -1) - { - for (int i = 0; i < 32; i++) - { - if (tex.FaceTextures[i] != null) - { - tex.FaceTextures[i].Rotation = (float)rotation; - } - } - tex.DefaultTexture.Rotation = (float)rotation; - m_host.UpdateTexture(tex); - return; - } - NotImplemented("llRotateTexture"); - return; - } - - public string llGetTexture(int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - if (face == -1) - { - face = 0; - } - if (face > -1) - { - LLObject.TextureEntryFace texface; - texface = tex.GetFace((uint)face); - return texface.TextureID.ToString(); - } - NotImplemented("llGetTexture"); - return ""; - } - - public void llSetPos(LSL_Types.Vector3 pos) - { - if (m_host.ParentID != 0) - { - m_host.UpdateOffSet(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); - } - else - { - m_host.UpdateGroupPosition(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); - } - } - - public LSL_Types.Vector3 llGetPos() - { - return new LSL_Types.Vector3(m_host.AbsolutePosition.X, - m_host.AbsolutePosition.Y, - m_host.AbsolutePosition.Z); - } - - public LSL_Types.Vector3 llGetLocalPos() - { - if (m_host.ParentID != 0) - { - return new LSL_Types.Vector3(m_host.OffsetPosition.X, - m_host.OffsetPosition.Y, - m_host.OffsetPosition.Z); - } - else - { - return new LSL_Types.Vector3(m_host.AbsolutePosition.X, - m_host.AbsolutePosition.Y, - m_host.AbsolutePosition.Z); - } - } - - public void llSetRot(LSL_Types.Quaternion rot) - { - m_host.UpdateRotation(new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s)); - } - - public LSL_Types.Quaternion llGetRot() - { - LLQuaternion q = m_host.RotationOffset; - return new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); - } - - public LSL_Types.Quaternion llGetLocalRot() - { - return new LSL_Types.Quaternion(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); - } - - public void llSetForce(LSL_Types.Vector3 force, int local) - { - NotImplemented("llSetForce"); - } - - public LSL_Types.Vector3 llGetForce() - { - NotImplemented("llGetForce"); - return new LSL_Types.Vector3(); - } - - public int llTarget(LSL_Types.Vector3 position, double range) - { - NotImplemented("llTarget"); - return 0; - } - - public void llTargetRemove(int number) - { - NotImplemented("llTargetRemove"); - } - - public int llRotTarget(LSL_Types.Quaternion rot, double error) - { - NotImplemented("llRotTarget"); - return 0; - } - - public void llRotTargetRemove(int number) - { - NotImplemented("llRotTargetRemove"); - } - - public void llMoveToTarget(LSL_Types.Vector3 target, double tau) - { - NotImplemented("llMoveToTarget"); - } - - public void llStopMoveToTarget() - { - NotImplemented("llStopMoveToTarget"); - } - - public void llApplyImpulse(LSL_Types.Vector3 force, int local) - { - NotImplemented("llApplyImpulse"); - } - - public void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local) - { - NotImplemented("llApplyRotationalImpulse"); - } - - public void llSetTorque(LSL_Types.Vector3 torque, int local) - { - NotImplemented("llSetTorque"); - } - - public LSL_Types.Vector3 llGetTorque() - { - NotImplemented("llGetTorque"); - return new LSL_Types.Vector3(); - } - - public void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local) - { - NotImplemented("llSetForceAndTorque"); - } - - public LSL_Types.Vector3 llGetVel() - { - return new LSL_Types.Vector3(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z); - } - - public LSL_Types.Vector3 llGetAccel() - { - return new LSL_Types.Vector3(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); - } - - public LSL_Types.Vector3 llGetOmega() - { - NotImplemented("llGetOmega"); - return new LSL_Types.Vector3(); - } - - public double llGetTimeOfDay() - { - NotImplemented("llGetTimeOfDay"); - return 0; - } - - public double llGetWallclock() - { - return DateTime.Now.TimeOfDay.TotalSeconds; - } - - public double llGetTime() - { - TimeSpan ScriptTime = DateTime.Now - m_timer; - return (double)(ScriptTime.TotalMilliseconds / 1000); - } - - public void llResetTime() - { - m_timer = DateTime.Now; - } - - public double llGetAndResetTime() - { - TimeSpan ScriptTime = DateTime.Now - m_timer; - m_timer = DateTime.Now; - return (double)(ScriptTime.TotalMilliseconds / 1000); - } - - public void llSound() - { - // This function has been deprecated - // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound - } - - public void llPlaySound(string sound, double volume) - { - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; - - LLUUID ownerID = m_host.OwnerID; - LLUUID objectID = m_host.UUID; - LLUUID soundID; - byte flags = 0; - - if (!LLUUID.TryParse(sound, out soundID)) - { - soundID = World.AssetCache.ExistsAsset(LSL_BaseClass.INVENTORY_SOUND, sound); // hack - - // search sound file from inventory - SceneObjectPart op = World.GetSceneObjectPart(objectID); - foreach (KeyValuePair item in op.TaskInventory) - { - string test = item.Value.type; - if (item.Value.name == sound) - { - soundID = item.Value.item_id; - break; - } - } - } - - List avatarts = World.GetAvatars(); - foreach (ScenePresence p in avatarts) - { - // TODO: some filtering by distance of avatar - p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)volume, flags); - } - } - - public void llLoopSound(string sound, double volume) - { - NotImplemented("llLoopSound"); - } - - public void llLoopSoundMaster(string sound, double volume) - { - NotImplemented("llLoopSoundMaster"); - } - - public void llLoopSoundSlave(string sound, double volume) - { - NotImplemented("llLoopSoundSlave"); - } - - public void llPlaySoundSlave(string sound, double volume) - { - NotImplemented("llPlaySoundSlave"); - } - - public void llTriggerSound(string sound, double volume) - { - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; - - LLUUID ownerID = m_host.OwnerID; - LLUUID objectID = m_host.UUID; - LLUUID parentID = this.m_host.GetRootPartUUID(); - LLUUID soundID; - LLVector3 position = this.m_host.AbsolutePosition; // region local - ulong regionHandle = World.RegionInfo.RegionHandle; - - if (!LLUUID.TryParse(sound, out soundID)) - { - soundID = World.AssetCache.ExistsAsset(LSL_BaseClass.INVENTORY_SOUND, sound); // hack - - // search sound file from inventory - SceneObjectPart op = World.GetSceneObjectPart(objectID); - foreach (KeyValuePair item in op.TaskInventory) - { - string test = item.Value.type; - if (item.Value.name == sound) - { - soundID = item.Value.item_id; - break; - } - } - } - - List avatarts = World.GetAvatars(); - foreach (ScenePresence p in avatarts) - { - // TODO: some filtering by distance of avatar - p.ControllingClient.SendTriggeredSound(soundID, ownerID, objectID, parentID, regionHandle, position, (float)volume); - } - } - - public void llStopSound() - { - NotImplemented("llStopSound"); - } - - public void llPreloadSound(string sound) - { - LLUUID ownerID = m_host.OwnerID; - LLUUID objectID = m_host.UUID; - LLUUID soundID; - - if (!LLUUID.TryParse(sound, out soundID)) - { - soundID = World.AssetCache.ExistsAsset(LSL_BaseClass.INVENTORY_SOUND, sound); // hack - - // search sound file from inventory - SceneObjectPart op = World.GetSceneObjectPart(objectID); - foreach (KeyValuePair item in op.TaskInventory) - { - string test = item.Value.type; - if (item.Value.name == sound) - { - soundID = item.Value.item_id; - break; - } - } - } - - List avatarts = World.GetAvatars(); - foreach (ScenePresence p in avatarts) - { - // TODO: some filtering by distance of avatar - p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID ); - } - } - - public string llGetSubString(string src, int start, int end) - { - return src.Substring(start, end); - } - - public string llDeleteSubString(string src, int start, int end) - { - return src.Remove(start, end - start); - } - - public string llInsertString(string dst, int position, string src) - { - return dst.Insert(position, src); - } - - public string llToUpper(string src) - { - return src.ToUpper(); - } - - public string llToLower(string src) - { - return src.ToLower(); - } - - public int llGiveMoney(string destination, int amount) - { - NotImplemented("llGiveMoney"); - return 0; - } - - public void llMakeExplosion() - { - NotImplemented("llMakeExplosion"); - } - - public void llMakeFountain() - { - NotImplemented("llMakeFountain"); - } - - public void llMakeSmoke() - { - NotImplemented("llMakeSmoke"); - } - - public void llMakeFire() - { - NotImplemented("llMakeFire"); - } - - public void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Quaternion rot, int param) - { - NotImplemented("llRezObject"); - } - - public void llLookAt(LSL_Types.Vector3 target, double strength, double damping) - { - NotImplemented("llLookAt"); - } - - public void llStopLookAt() - { - NotImplemented("llStopLookAt"); - } - - public void llSetTimerEvent(double sec) - { - // Setting timer repeat - m_ScriptEngine.m_LSLLongCmdHandler.SetTimerEvent(m_localID, m_itemID, sec); - } - - public void llSleep(double sec) - { - Thread.Sleep((int)(sec * 1000)); - } - - public double llGetMass() - { - return m_host.GetMass(); - } - - public void llCollisionFilter(string name, string id, int accept) - { - NotImplemented("llCollisionFilter"); - } - - public void llTakeControls(int controls, int accept, int pass_on) - { - NotImplemented("llTakeControls"); - } - - public void llReleaseControls() - { - NotImplemented("llReleaseControls"); - } - - public void llAttachToAvatar(int attachment) - { - NotImplemented("llAttachToAvatar"); - } - - public void llDetachFromAvatar() - { - NotImplemented("llDetachFromAvatar"); - } - - public void llTakeCamera() - { - NotImplemented("llTakeCamera"); - } - - public void llReleaseCamera() - { - NotImplemented("llReleaseCamera"); - } - - public string llGetOwner() - { - return m_host.ObjectOwner.ToString(); - } - - public void llInstantMessage(string user, string message) - { - NotImplemented("llInstantMessage"); - - // 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.) - - // 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()); - } - - public void llEmail(string address, string subject, string message) - { - NotImplemented("llEmail"); - } - - public void llGetNextEmail(string address, string subject) - { - NotImplemented("llGetNextEmail"); - } - - public string llGetKey() - { - return m_host.UUID.ToString(); - } - - public void llSetBuoyancy(double buoyancy) - { - NotImplemented("llSetBuoyancy"); - } - - public void llSetHoverHeight(double height, int water, double tau) - { - NotImplemented("llSetHoverHeight"); - } - - public void llStopHover() - { - NotImplemented("llStopHover"); - } - - public void llMinEventDelay(double delay) - { - NotImplemented("llMinEventDelay"); - } - - public void llSoundPreload() - { - NotImplemented("llSoundPreload"); - } - - public void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping) - { - NotImplemented("llRotLookAt"); - } - - public int llStringLength(string str) - { - if (str.Length > 0) - { - return str.Length; - } - else - { - return 0; - } - } - - public void llStartAnimation(string anim) - { - NotImplemented("llStartAnimation"); - } - - public void llStopAnimation(string anim) - { - NotImplemented("llStopAnimation"); - } - - public void llPointAt() - { - NotImplemented("llPointAt"); - } - - public void llStopPointAt() - { - NotImplemented("llStopPointAt"); - } - - public void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain) - { - m_host.RotationalVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); - m_host.AngularVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); - m_host.ScheduleTerseUpdate(); - m_host.SendTerseUpdateToAllClients(); - //NotImplemented("llTargetOmega"); - } - - public int llGetStartParameter() - { - NotImplemented("llGetStartParameter"); - return 0; - } - - public void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos) - { - NotImplemented("llGodLikeRezObject"); - } - - public void llRequestPermissions(string agent, int perm) - { - NotImplemented("llRequestPermissions"); - } - - public string llGetPermissionsKey() - { - NotImplemented("llGetPermissionsKey"); - return ""; - } - - public int llGetPermissions() - { - NotImplemented("llGetPermissions"); - return 0; - } - - public int llGetLinkNumber() - { - return m_host.LinkNum; - } - - public void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face) - { - SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); - if (linknumber > -1) - { - LLObject.TextureEntry tex = part.Shape.Textures; - LLColor texcolor; - if (face > -1) - { - texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.FaceTextures[face].RGBA = texcolor; - part.UpdateTexture(tex); - return; - } - else if (face == -1) - { - texcolor = tex.DefaultTexture.RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.DefaultTexture.RGBA = texcolor; - for (uint i = 0; i < 32; i++) - { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.FaceTextures[i].RGBA = texcolor; - } - } - texcolor = tex.DefaultTexture.RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.DefaultTexture.RGBA = texcolor; - part.UpdateTexture(tex); - return; - } - return; - } - else if (linknumber == -1) - { - int num = m_host.ParentGroup.PrimCount; - for (int w = 0; w < num; w++) - { - linknumber = w; - part = m_host.ParentGroup.GetLinkNumPart(linknumber); - LLObject.TextureEntry tex = part.Shape.Textures; - LLColor texcolor; - if (face > -1) - { - texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.FaceTextures[face].RGBA = texcolor; - part.UpdateTexture(tex); - } - else if (face == -1) - { - texcolor = tex.DefaultTexture.RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.DefaultTexture.RGBA = texcolor; - for (uint i = 0; i < 32; i++) - { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.FaceTextures[i].RGBA = texcolor; - } - } - texcolor = tex.DefaultTexture.RGBA; - texcolor.R = (float)Math.Abs(color.x - 1); - texcolor.G = (float)Math.Abs(color.y - 1); - texcolor.B = (float)Math.Abs(color.z - 1); - tex.DefaultTexture.RGBA = texcolor; - part.UpdateTexture(tex); - } - } - return; - } - else - { - NotImplemented("llSetLinkColor"); - } - } - - public void llCreateLink(string target, int parent) - { - NotImplemented("llCreateLink"); - } - - public void llBreakLink(int linknum) - { - NotImplemented("llBreakLink"); - } - - public void llBreakAllLinks() - { - NotImplemented("llBreakAllLinks"); - } - - public string llGetLinkKey(int linknum) - { - SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); - if (part != null) - { - return part.UUID.ToString(); - } - else - { - return "00000000-0000-0000-0000-000000000000"; - } - } - - public string llGetLinkName(int linknum) - { - SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); - if (part != null) - { - return part.Name; - } - else - { - return "00000000-0000-0000-0000-000000000000"; - } - } - - public int llGetInventoryNumber(int type) - { - NotImplemented("llGetInventoryNumber"); - return 0; - } - - public string llGetInventoryName(int type, int number) - { - NotImplemented("llGetInventoryName"); - return ""; - } - - public void llSetScriptState(string name, int run) - { - NotImplemented("llSetScriptState"); - } - - public double llGetEnergy() - { - return 1.0f; - } - - public void llGiveInventory(string destination, string inventory) - { - NotImplemented("llGiveInventory"); - } - - public void llRemoveInventory(string item) - { - NotImplemented("llRemoveInventory"); - } - - public void llSetText(string text, LSL_Types.Vector3 color, double alpha) - { - Vector3 av3 = new Vector3((float)color.x, (float)color.y, (float)color.z); - m_host.SetText(text, av3, alpha); - } - - public double llWater(LSL_Types.Vector3 offset) - { - return World.RegionInfo.EstateSettings.waterHeight; - } - - public void llPassTouches(int pass) - { - NotImplemented("llPassTouches"); - } - - public string llRequestAgentData(string id, int data) - { - NotImplemented("llRequestAgentData"); - return ""; - } - - public string llRequestInventoryData(string name) - { - NotImplemented("llRequestInventoryData"); - return ""; - } - - public void llSetDamage(double damage) - { - NotImplemented("llSetDamage"); - } - - public void llTeleportAgentHome(string agent) - { - NotImplemented("llTeleportAgentHome"); - } - - public void llModifyLand(int action, int brush) - { - } - - public void llCollisionSound(string impact_sound, double impact_volume) - { - NotImplemented("llCollisionSound"); - } - - public void llCollisionSprite(string impact_sprite) - { - NotImplemented("llCollisionSprite"); - } - - public string llGetAnimation(string id) - { - NotImplemented("llGetAnimation"); - return ""; - } - - public void llResetScript() - { - m_ScriptEngine.m_ScriptManager.ResetScript(m_localID, m_itemID); - } - - public void llMessageLinked(int linknum, int num, string str, string id) - { - } - - public void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local) - { - } - - public void llPassCollisions(int pass) - { - } - - public string llGetScriptName() - { - return ""; - } - - public int llGetNumberOfSides() - { - return 0; - } - - public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle) - { - return new LSL_Types.Quaternion(); - } - - public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot) - { - return new LSL_Types.Vector3(); - } - - public void llRot2Angle() - { - } - - public double llAcos(double val) - { - return (double)Math.Acos(val); - } - - public double llAsin(double val) - { - return (double)Math.Asin(val); - } - - public double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b) - { - return 0; - } - - public string llGetInventoryKey(string name) - { - return ""; - } - - public void llAllowInventoryDrop(int add) - { - } - - public LSL_Types.Vector3 llGetSunDirection() - { - return new LSL_Types.Vector3(); - } - - public LSL_Types.Vector3 llGetTextureOffset(int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - LSL_Types.Vector3 offset; - if (face == -1) - { - face = 0; - } - offset.x = tex.GetFace((uint)face).OffsetU; - offset.y = tex.GetFace((uint)face).OffsetV; - offset.z = 0.0; - return offset; - } - - public LSL_Types.Vector3 llGetTextureScale(int side) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - LSL_Types.Vector3 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 double llGetTextureRot(int face) - { - LLObject.TextureEntry tex = m_host.Shape.Textures; - if (face == -1) - { - face = 0; - } - return tex.GetFace((uint)face).Rotation; - } - - public int llSubStringIndex(string source, string pattern) - { - return source.IndexOf(pattern); - } - - public string llGetOwnerKey(string id) - { - NotImplemented("llGetOwnerKey"); - return ""; - } - - public LSL_Types.Vector3 llGetCenterOfMass() - { - NotImplemented("llGetCenterOfMass"); - return new LSL_Types.Vector3(); - } - - public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending) - { - // SortedList sorted = new SortedList(); - // Add chunks to an array - //int s = stride; - //if (s < 1) - // s = 1; - //int c = 0; - //LSL_Types.list chunk = new LSL_Types.list(); - //string chunkString = ""; - //foreach (string element in src) - //{ - // c++; - // if (c > s) - // { - // sorted.Add(chunkString, chunk); - // chunkString = ""; - // chunk = new LSL_Types.list(); - // c = 0; - // } - // chunk.Add(element); - // chunkString += element.ToString(); - //} - //if (chunk.Count > 0) - // sorted.Add(chunkString, chunk); - - //LSL_Types.list ret = new LSL_Types.list(); - //foreach (LSL_Types.list ls in sorted.Values) - //{ - // ret.AddRange(ls); - //} - - //if (ascending == LSL_BaseClass.TRUE) - // return ret; - //ret.Reverse(); - //return ret; - NotImplemented("llListSort"); - return new LSL_Types.list(); - } - - public int llGetListLength(LSL_Types.list src) - { - return src.Length; - } - - public int llList2Integer(LSL_Types.list src, int index) - { - if (index < 0) - { - index = src.Length + index; - } - if (index >= src.Length) - { - return 0; - } - return Convert.ToInt32(src.Data[index]); - } - - public double osList2Double(LSL_Types.list src, int index) - { - if (index < 0) - { - index = src.Length + index; - } - if (index >= src.Length) - { - return 0.0; - } - return Convert.ToDouble(src.Data[index]); - } - - public double llList2Float(LSL_Types.list src, int index) - { - if (index < 0) - { - index = src.Length + index; - } - if (index >= src.Length) - { - return 0.0; - } - return Convert.ToSingle(src.Data[index]); - } - - public string llList2String(LSL_Types.list src, int index) - { - if (index < 0) - { - index = src.Length + index; - } - if (index >= src.Length) - { - return ""; - } - return src.Data[index].ToString(); - } - - public string llList2Key(LSL_Types.list src, int index) - { - if (index < 0) - { - index = src.Length + index; - } - if (index >= src.Length) - { - return "00000000-0000-0000-0000-000000000000"; - } - //return OpenSim.Framework.ToString(src[index]); - LLUUID tmpkey; - if (LLUUID.TryParse(src.Data[index].ToString(), out tmpkey)) - { - return tmpkey.ToString(); - } - else - { - return "00000000-0000-0000-0000-000000000000"; - } - } - - public LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index) - { - if (index < 0) - { - index = src.Length + index; - } - if (index >= src.Length) - { - return new LSL_Types.Vector3(0, 0, 0); - } - if (src.Data[index].GetType() == typeof(OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3)) - { - return (LSL_Types.Vector3)src.Data[index]; - } - else - { - return new LSL_Types.Vector3(0, 0, 0); - } - } - - public LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index) - { - if (index < 0) - { - index = src.Length + index; - } - if (index >= src.Length) - { - return new LSL_Types.Quaternion(0, 0, 0, 1); - } - if (src.Data[index].GetType() == typeof(OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion)) - { - return (LSL_Types.Quaternion)src.Data[index]; - } - else - { - return new LSL_Types.Quaternion(0, 0, 0, 1); - } - } - - public LSL_Types.list llList2List(LSL_Types.list src, int start, int end) - { - return src.GetSublist(start, end); - } - - public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end) - { - //LSL_Types.list ret = new LSL_Types.list(src); - //ret.RemoveRange(start, end - start); - //return ret; - - // Just a hunch - needs testing - return src.GetSublist(end, start); - } - - public int llGetListEntryType(LSL_Types.list src, int index) - { - if (index < 0) - { - index = src.Length + index; - } - if (index >= src.Length) - { - return 0; - } - - if (src.Data[index] is System.Int32) - return 1; - if (src.Data[index] is System.Double) - return 2; - if (src.Data[index] is System.String) - { - LLUUID tuuid; - if (LLUUID.TryParse(src.Data[index].ToString(), out tuuid)) - { - return 3; - } - else - { - return 4; - } - } - if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3) - return 5; - if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion) - return 6; - if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.list) - return 7; - return 0; - - } - - public string llList2CSV(LSL_Types.list src) - { - string ret = ""; - foreach (object o in src.Data) - { - ret = ret + o.ToString() + ","; - } - ret = ret.Substring(0, ret.Length - 2); - return ret; - } - - public LSL_Types.list llCSV2List(string src) - { - return new LSL_Types.list(src.Split(",".ToCharArray())); - } - - public LSL_Types.list llListRandomize(LSL_Types.list src, int stride) - { - //int s = stride; - //if (s < 1) - // s = 1; - - // This is a cowardly way of doing it ;) - // TODO: Instead, randomize and check if random is mod stride or if it can not be, then array.removerange - //List tmp = new List(); - - // Add chunks to an array - //int c = 0; - //LSL_Types.list chunk = new LSL_Types.list(); - //foreach (string element in src) - //{ - // c++; - // if (c > s) - // { - // tmp.Add(chunk); - // chunk = new LSL_Types.list(); - // c = 0; - // } - // chunk.Add(element); - //} - //if (chunk.Count > 0) - // tmp.Add(chunk); - - // Decreate (<- what kind of word is that? :D ) array back into a list - //int rnd; - //LSL_Types.list ret = new LSL_Types.list(); - //while (tmp.Count > 0) - //{ - // rnd = Util.RandomClass.Next(tmp.Count); - // foreach (string str in tmp[rnd]) - // { - // ret.Add(str); - // } - // tmp.RemoveAt(rnd); - //} - - //return ret; - NotImplemented("llListRandomize"); - return new LSL_Types.list(); - } - - public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride) - { - LSL_Types.list ret = new LSL_Types.list(); - //int s = stride; - //if (s < 1) - // s = 1; - - //int sc = s; - //for (int i = start; i < src.Count; i++) - //{ - // sc--; - // if (sc == 0) - // { - // sc = s; - // // Addthis - // ret.Add(src[i]); - // } - // if (i == end) - // break; - //} - NotImplemented("llList2ListStrided"); - return ret; - } - - public LSL_Types.Vector3 llGetRegionCorner() - { - return new LSL_Types.Vector3(World.RegionInfo.RegionLocX * 256, World.RegionInfo.RegionLocY * 256, 0); - } - - public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start) - { - return dest.GetSublist(0, start - 1) + src + dest.GetSublist(start, -1); - } - - public int llListFindList(LSL_Types.list src, LSL_Types.list test) - { - //foreach (string s in test) - //{ - // for (int ci = 0; ci < src.Count; ci++) - // { - // if (s == src[ci]) - // return ci; - // } - //} - NotImplemented("llListFindList"); - return -1; - } - - public string llGetObjectName() - { - return m_host.Name; - } - - public void llSetObjectName(string name) - { - m_host.Name = name; - } - - public string llGetDate() - { - DateTime date = DateTime.Now.ToUniversalTime(); - string result = date.ToString("yyyy-MM-dd"); - return result; - } - - public int llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir) - { - NotImplemented("llEdgeOfWorld"); - return 0; - } - - public int llGetAgentInfo(string id) - { - NotImplemented("llGetAgentInfo"); - return 0; - } - - public void llAdjustSoundVolume(double volume) - { - NotImplemented("llAdjustSoundVolume"); - } - - public void llSetSoundQueueing(int queue) - { - NotImplemented("llSetSoundQueueing"); - } - - public void llSetSoundRadius(double radius) - { - NotImplemented("llSetSoundRadius"); - } - - public string llKey2Name(string id) - { - NotImplemented("llKey2Name"); - return ""; - } - - public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) - { - NotImplemented("llSetTextureAnim"); - } - - public void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, - LSL_Types.Vector3 bottom_south_west) - { - NotImplemented("llTriggerSoundLimited"); - } - - public void llEjectFromLand(string pest) - { - NotImplemented("llEjectFromLand"); - } - - public void llParseString2List() - { - NotImplemented("llParseString2List"); - } - - public int llOverMyLand(string id) - { - NotImplemented("llOverMyLand"); - return 0; - } - - public string llGetLandOwnerAt(LSL_Types.Vector3 pos) - { - return World.GetLandOwner((float)pos.x, (float)pos.y).ToString(); - } - - public string llGetNotecardLine(string name, int line) - { - NotImplemented("llGetNotecardLine"); - return ""; - } - - public LSL_Types.Vector3 llGetAgentSize(string id) - { - NotImplemented("llGetAgentSize"); - return new LSL_Types.Vector3(); - } - - public int llSameGroup(string agent) - { - NotImplemented("llSameGroup"); - return 0; - } - - public void llUnSit(string id) - { - NotImplemented("llUnSit"); - } - - public LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset) - { - NotImplemented("llGroundSlope"); - return new LSL_Types.Vector3(); - } - - public LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset) - { - NotImplemented("llGroundNormal"); - return new LSL_Types.Vector3(); - } - - public LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset) - { - NotImplemented("llGroundContour"); - return new LSL_Types.Vector3(); - } - - public int llGetAttached() - { - NotImplemented("llGetAttached"); - return 0; - } - - public int llGetFreeMemory() - { - NotImplemented("llGetFreeMemory"); - return 0; - } - - public string llGetRegionName() - { - return World.RegionInfo.RegionName; - } - - public double llGetRegionTimeDilation() - { - return (double)World.TimeDilation; - } - - public double llGetRegionFPS() - { - return 10.0f; - } - - /* 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, - 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 - } - - public void llParticleSystem(List rules) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - for (int i = 0; i < rules.Count; i += 2) - { - switch ((int)rules[i]) - { - case (int)LSL_BaseClass.PSYS_PART_FLAGS: - prules.PartFlags = (uint)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_PART_START_COLOR: - prules.PartStartColor = (LLColor)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_PART_START_ALPHA: - //what is the cast? prules.PartStartColor = (LSL_Types.Vec)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_PART_END_COLOR: - prules.PartEndColor = (LLColor)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_PART_END_ALPHA: - //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_PART_START_SCALE: - //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_PART_END_SCALE: - //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_PART_MAX_AGE: - prules.MaxAge = (float)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_ACCEL: - //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_PATTERN: - //what is the cast? prules.PartStartColor = (LLColor)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_TEXTURE: - prules.Texture = (LLUUID)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_BURST_RATE: - prules.BurstRate = (float)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_BURST_PART_COUNT: - prules.BurstPartCount = (byte)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_BURST_RADIUS: - prules.BurstRadius = (float)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_BURST_SPEED_MIN: - prules.BurstSpeedMin = (float)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_BURST_SPEED_MAX: - prules.BurstSpeedMax = (float)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_MAX_AGE: - prules.MaxAge = (float)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_TARGET_KEY: - prules.Target = (LLUUID)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_OMEGA: - //cast?? prules.MaxAge = (float)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_ANGLE_BEGIN: - prules.InnerAngle = (float)rules[i + 1]; - break; - - case (int)LSL_BaseClass.PSYS_SRC_ANGLE_END: - prules.OuterAngle = (float)rules[i + 1]; - break; - } - } - - m_host.AddNewParticleSystem(prules); - } - - public void llGroundRepel(double height, int water, double tau) - { - NotImplemented("llGroundRepel"); - } - - public void llGiveInventoryList() - { - NotImplemented("llGiveInventoryList"); - } - - public void llSetVehicleType(int type) - { - NotImplemented("llSetVehicleType"); - } - - public void llSetVehicledoubleParam(int param, double value) - { - NotImplemented("llSetVehicledoubleParam"); - } - - public void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec) - { - NotImplemented("llSetVehicleVectorParam"); - } - - public void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot) - { - NotImplemented("llSetVehicleRotationParam"); - } - - public void llSetVehicleFlags(int flags) - { - NotImplemented("llSetVehicleFlags"); - } - - public void llRemoveVehicleFlags(int flags) - { - NotImplemented("llRemoveVehicleFlags"); - } - - public void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot) - { - // LSL quaternions can normalize to 0, normal Quaternions can't. - if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) - rot.z = 1; // ZERO_ROTATION = 0,0,0,1 - - m_host.SetSitTarget(new Vector3((float)offset.x, (float)offset.y, (float)offset.z), new Quaternion((float)rot.s, (float)rot.x, (float)rot.y, (float)rot.z)); - } - - public string llAvatarOnSitTarget() - { - LLUUID AVID = m_host.GetAvatarOnSitTarget(); - - if (AVID != LLUUID.Zero) - return AVID.ToString(); - else - return ""; - } - - public void llAddToLandPassList(string avatar, double hours) - { - NotImplemented("llAddToLandPassList"); - } - - public void llSetTouchText(string text) - { - m_host.TouchName = text; - } - - public void llSetSitText(string text) - { - m_host.SitName = text; - } - - public void llSetCameraEyeOffset(LSL_Types.Vector3 offset) - { - NotImplemented("llSetCameraEyeOffset"); - } - - public void llSetCameraAtOffset(LSL_Types.Vector3 offset) - { - NotImplemented("llSetCameraAtOffset"); - } - - public string llDumpList2String(LSL_Types.list src, string seperator) - { - if (src.Length == 0) - { - return ""; - } - string ret = ""; - foreach (object o in src.Data) - { - ret = ret + o.ToString() + seperator; - } - ret = ret.Substring(0, ret.Length - seperator.Length); - return ret; - } - - public void llScriptDanger(LSL_Types.Vector3 pos) - { - NotImplemented("llScriptDanger"); - } - - public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel) - { - LLUUID av = new LLUUID(); - if (!LLUUID.TryParse(avatar, out av)) - { - LSLError("First parameter to llDialog needs to be a key"); - return; - } - string[] buts = new string[buttons.Length]; - for (int i = 0; i < buttons.Length; i++) - { - buts[i] = buttons.Data[i].ToString(); - } - World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new LLUUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); - //NotImplemented("llDialog"); - } - - public void llVolumeDetect(int detect) - { - NotImplemented("llVolumeDetect"); - } - - public void llResetOtherScript(string name) - { - NotImplemented("llResetOtherScript"); - } - - public int llGetScriptState(string name) - { - NotImplemented("llGetScriptState"); - return 0; - } - - public void llRemoteLoadScript() - { - NotImplemented("llRemoteLoadScript"); - } - - public void llSetRemoteScriptAccessPin(int pin) - { - NotImplemented("llSetRemoteScriptAccessPin"); - } - - public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) - { - NotImplemented("llRemoteLoadScriptPin"); - } - - // remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) - // Not sure where these constants should live: - // REMOTE_DATA_CHANNEL = 1 - // REMOTE_DATA_REQUEST = 2 - // REMOTE_DATA_REPLY = 3 - public void llOpenRemoteDataChannel() - { - IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); - if (xmlrpcMod.IsEnabled()) - { - LLUUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID); - object[] resobj = new object[] { 1, channelID.ToString(), LLUUID.Zero.ToString(), "", 0, "" }; - m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(m_localID, m_itemID, "remote_data", resobj); - } - } - - public string llSendRemoteData(string channel, string dest, int idata, string sdata) - { - NotImplemented("llSendRemoteData"); - return ""; - } - - public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) - { - IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); - xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); - } - - public void llCloseRemoteDataChannel(string channel) - { - IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); - xmlrpcMod.CloseXMLRPCChannel(channel); - } - - public string llMD5String(string src, int nonce) - { - return Util.Md5Hash(src + ":" + nonce.ToString()); - } - - public void llSetPrimitiveParams(LSL_Types.list rules) - { - NotImplemented("llSetPrimitiveParams"); - } - - public string llStringToBase64(string str) - { - try - { - byte[] encData_byte = new byte[str.Length]; - encData_byte = Encoding.UTF8.GetBytes(str); - string encodedData = Convert.ToBase64String(encData_byte); - return encodedData; - } - catch (Exception e) - { - throw new Exception("Error in base64Encode" + e.Message); - } - } - - public string llBase64ToString(string str) - { - UTF8Encoding encoder = new UTF8Encoding(); - Decoder utf8Decode = encoder.GetDecoder(); - try - { - byte[] todecode_byte = Convert.FromBase64String(str); - int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); - char[] decoded_char = new char[charCount]; - utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); - string result = new String(decoded_char); - return result; - } - catch (Exception e) - { - throw new Exception("Error in base64Decode" + e.Message); - } - } - - public void llXorBase64Strings() - { - throw new Exception("Command deprecated! Use llXorBase64StringsCorrect instead."); - } - - public void llRemoteDataSetRegion() - { - NotImplemented("llRemoteDataSetRegion"); - } - - public double llLog10(double val) - { - return (double)Math.Log10(val); - } - - public double llLog(double val) - { - return (double)Math.Log(val); - } - - public LSL_Types.list llGetAnimationList(string id) - { - NotImplemented("llGetAnimationList"); - return new LSL_Types.list(); - } - - public void llSetParcelMusicURL(string url) - { - LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); - if (landowner == null) - { - return; - } - if (landowner != m_host.ObjectOwner) - { - return; - } - World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); - } - - public LSL_Types.Vector3 llGetRootPosition() - { - return new LSL_Types.Vector3(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z); - } - - public LSL_Types.Quaternion llGetRootRotation() - { - return new LSL_Types.Quaternion(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W); - } - - public string llGetObjectDesc() - { - return m_host.Description; - } - - public void llSetObjectDesc(string desc) - { - m_host.Description = desc; - } - - public string llGetCreator() - { - return m_host.ObjectCreator.ToString(); - } - - public string llGetTimestamp() - { - return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); - } - - public void llSetLinkAlpha(int linknumber, double alpha, int face) - { - SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); - if (linknumber > -1) - { - LLObject.TextureEntry tex = part.Shape.Textures; - LLColor texcolor; - if (face > -1) - { - texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.FaceTextures[face].RGBA = texcolor; - part.UpdateTexture(tex); - return; - } - else if (face == -1) - { - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.DefaultTexture.RGBA = texcolor; - for (uint i = 0; i < 32; i++) - { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.FaceTextures[i].RGBA = texcolor; - } - } - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.DefaultTexture.RGBA = texcolor; - part.UpdateTexture(tex); - return; - } - return; - } - else if (linknumber == -1) - { - int num = m_host.ParentGroup.PrimCount; - for (int w = 0; w < num; w++) - { - linknumber = w; - part = m_host.ParentGroup.GetLinkNumPart(linknumber); - LLObject.TextureEntry tex = part.Shape.Textures; - LLColor texcolor; - if (face > -1) - { - texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.FaceTextures[face].RGBA = texcolor; - part.UpdateTexture(tex); - } - else if (face == -1) - { - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.DefaultTexture.RGBA = texcolor; - for (uint i = 0; i < 32; i++) - { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.FaceTextures[i].RGBA = texcolor; - } - } - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = (float)Math.Abs(alpha - 1); - tex.DefaultTexture.RGBA = texcolor; - part.UpdateTexture(tex); - } - } - return; - } - else - { - NotImplemented("llSetLinkAlpha"); - } - } - - public int llGetNumberOfPrims() - { - return m_host.ParentGroup.PrimCount; - } - - public string llGetNumberOfNotecardLines(string name) - { - NotImplemented("llGetNumberOfNotecardLines"); - return ""; - } - - public LSL_Types.list llGetBoundingBox(string obj) - { - NotImplemented("llGetBoundingBox"); - return new LSL_Types.list(); - } - - public LSL_Types.Vector3 llGetGeometricCenter() - { - return new LSL_Types.Vector3(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); - } - - public void llGetPrimitiveParams() - { - NotImplemented("llGetPrimitiveParams"); - } - - public string llIntegerToBase64(int number) - { - NotImplemented("llIntegerToBase64"); - return ""; - } - - public int llBase64ToInteger(string str) - { - NotImplemented("llBase64ToInteger"); - return 0; - } - - public double llGetGMTclock() - { - return DateTime.UtcNow.TimeOfDay.TotalSeconds; - } - - public string llGetSimulatorHostname() - { - return System.Environment.MachineName; - } - - public void llSetLocalRot(LSL_Types.Quaternion rot) - { - m_host.RotationOffset = new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); - } - - public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers) - { - NotImplemented("llParseStringKeepNulls"); - return new LSL_Types.list(); - } - - public void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, - LSL_Types.Quaternion rot, int param) - { - NotImplemented("llRezAtRoot"); - } - - public int llGetObjectPermMask(int mask) - { - NotImplemented("llGetObjectPermMask"); - return 0; - } - - public void llSetObjectPermMask(int mask, int value) - { - NotImplemented("llSetObjectPermMask"); - } - - public void llGetInventoryPermMask(string item, int mask) - { - NotImplemented("llGetInventoryPermMask"); - } - - public void llSetInventoryPermMask(string item, int mask, int value) - { - NotImplemented("llSetInventoryPermMask"); - } - - public string llGetInventoryCreator(string item) - { - NotImplemented("llGetInventoryCreator"); - return ""; - } - - public void llOwnerSay(string msg) - { - //temp fix so that lsl wiki examples aren't annoying to use to test other functions - World.SimChat(Helpers.StringToField(msg), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID); - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Say, 0, m_host.Name, msg); - } - - public void llRequestSimulatorData(string simulator, int data) - { - NotImplemented("llRequestSimulatorData"); - } - - public void llForceMouselook(int mouselook) - { - NotImplemented("llForceMouselook"); - } - - public double llGetObjectMass(string id) - { - NotImplemented("llGetObjectMass"); - return 0; - } - - public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end) - { - return dest.GetSublist(0, start - 1) + src + dest.GetSublist(end + 1, -1); - } - - public void llLoadURL(string avatar_id, string message, string url) - { - LLUUID avatarId = new LLUUID(avatar_id); - m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message, - url); - } - - public void llParcelMediaCommandList(LSL_Types.list commandList) - { - NotImplemented("llParcelMediaCommandList"); - } - - public void llParcelMediaQuery() - { - NotImplemented("llParcelMediaQuery"); - } - - public int llModPow(int a, int b, int c) - { - Int64 tmp = 0; - Int64 val = Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); - return Convert.ToInt32(tmp); - } - - public int llGetInventoryType(string name) - { - NotImplemented("llGetInventoryType"); - return 0; - } - - public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) - { - NotImplemented("llSetPayPrice"); - } - - public LSL_Types.Vector3 llGetCameraPos() - { - NotImplemented("llGetCameraPos"); - return new LSL_Types.Vector3(); - } - - public LSL_Types.Quaternion llGetCameraRot() - { - NotImplemented("llGetCameraRot"); - return new LSL_Types.Quaternion(); - } - - public void llSetPrimURL() - { - NotImplemented("llSetPrimURL"); - } - - public void llRefreshPrimURL() - { - NotImplemented("llRefreshPrimURL"); - } - - public string llEscapeURL(string url) - { - try - { - return Uri.EscapeUriString(url); - } - catch (Exception ex) - { - return "llEscapeURL: " + ex.ToString(); - } - } - - public string llUnescapeURL(string url) - { - try - { - return Uri.UnescapeDataString(url); - } - catch (Exception ex) - { - return "llUnescapeURL: " + ex.ToString(); - } - } - - public void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at) - { - libsecondlife.LLVector3 position = new LLVector3((float)pos.x, (float)pos.y, (float)pos.z); - libsecondlife.LLVector3 lookAt = new LLVector3((float)look_at.x, (float)look_at.y, (float)look_at.z); - ScenePresence user = this.World.GetScenePresence(this.m_host.TouchedBy); - user.ControllingClient.SendScriptTeleportRequest(this.m_host.Name, simname, position, lookAt); - } - - public void llAddToLandBanList(string avatar, double hours) - { - NotImplemented("llAddToLandBanList"); - } - - public void llRemoveFromLandPassList(string avatar) - { - NotImplemented("llRemoveFromLandPassList"); - } - - public void llRemoveFromLandBanList(string avatar) - { - NotImplemented("llRemoveFromLandBanList"); - } - - public void llSetCameraParams(LSL_Types.list rules) - { - NotImplemented("llSetCameraParams"); - } - - public void llClearCameraParams() - { - NotImplemented("llClearCameraParams"); - } - - public double llListStatistics(int operation, LSL_Types.list src) - { - NotImplemented("llListStatistics"); - return 0; - } - - public int llGetUnixTime() - { - return Util.UnixTimeSinceEpoch(); - } - - public int llGetParcelFlags(LSL_Types.Vector3 pos) - { - NotImplemented("llGetParcelFlags"); - return 0; - } - - public int llGetRegionFlags() - { - NotImplemented("llGetRegionFlags"); - return 0; - } - - public string llXorBase64StringsCorrect(string str1, string str2) - { - string ret = ""; - string src1 = llBase64ToString(str1); - string src2 = llBase64ToString(str2); - int c = 0; - for (int i = 0; i < src1.Length; i++) - { - ret += src1[i] ^ src2[c]; - - c++; - if (c > src2.Length) - c = 0; - } - return llStringToBase64(ret); - } - - public string llHTTPRequest(string url, LSL_Types.list parameters, string body) - { - IHttpRequests httpScriptMod = - m_ScriptEngine.World.RequestModuleInterface(); - List param = new List(); - foreach (object o in parameters.Data) - { - param.Add(o.ToString()); - } - LLUUID reqID = httpScriptMod. - StartHttpRequest(m_localID, m_itemID, url, param, body); - - if (reqID != null) - return reqID.ToString(); - else - return null; - } - - public void llResetLandBanList() - { - NotImplemented("llResetLandBanList"); - } - - public void llResetLandPassList() - { - NotImplemented("llResetLandPassList"); - } - - public int llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide) - { - NotImplemented("llGetParcelPrimCount"); - return 0; - } - - public LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos) - { - NotImplemented("llGetParcelPrimOwners"); - return new LSL_Types.list(); - } - - public int llGetObjectPrimCount(string object_id) - { - SceneObjectPart part = World.GetSceneObjectPart(new LLUUID(object_id)); - if (part == null) - { - return 0; - } - else - { - return part.ParentGroup.Children.Count; - } - } - - public int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide) - { - // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation - // Which probably will be irrelevent in OpenSim.... - LandData land = World.GetLandData((float)pos.x, (float)pos.y); - float bonusfactor = World.RegionInfo.EstateSettings.objectBonusFactor; - if (land == null) - { - return 0; - } - if (sim_wide == 1) - { - decimal v = land.simwideArea * (decimal)(0.22) * (decimal)bonusfactor; - return (int)v; - } - else - { - decimal v = land.area * (decimal)(0.22) * (decimal)bonusfactor; - return (int)v; - } - - } - - public LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param) - { - LandData land = World.GetLandData((float)pos.x, (float)pos.y); - if (land == null) - { - return new LSL_Types.list(0); - } - LSL_Types.list ret = new LSL_Types.list(); - foreach (object o in param.Data) - { - switch (o.ToString()) - { - case "0": - ret = ret + new LSL_Types.list(land.landName); - break; - case "1": - ret = ret + new LSL_Types.list(land.landDesc); - break; - case "2": - ret = ret + new LSL_Types.list(land.ownerID.ToString()); - break; - case "3": - ret = ret + new LSL_Types.list(land.groupID.ToString()); - break; - case "4": - ret = ret + new LSL_Types.list(land.area); - break; - default: - ret = ret + new LSL_Types.list(0); - break; - } - } - return ret; - } - - // - // OpenSim functions - // - public int osTerrainSetHeight(int x, int y, double val) - { - if (x > 255 || x < 0 || y > 255 || y < 0) - LSLError("osTerrainSetHeight: Coordinate out of bounds"); - - if (World.PermissionsMngr.CanTerraform(m_host.OwnerID, new LLVector3(x, y, 0))) - { - World.Terrain.Set(x, y, val); - return 1; - } - else - { - return 0; - } - } - - public double osTerrainGetHeight(int x, int y) - { - if (x > 255 || x < 0 || y > 255 || y < 0) - LSLError("osTerrainGetHeight: Coordinate out of bounds"); - - return World.Terrain.GetHeight(x, y); - } - - public int osRegionRestart(double seconds) - { - if (World.PermissionsMngr.CanRestartSim(m_host.OwnerID)) - { - World.Restart((float)seconds); - return 1; - } - else - { - return 0; - } - } - - public void osRegionNotice(string msg) - { - World.SendGeneralAlert(msg); - } - - public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, - int timer) - { - if (dynamicID == "") - { - IDynamicTextureManager textureManager = World.RequestModuleInterface(); - LLUUID createdTexture = - textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, - extraParams, timer); - return createdTexture.ToString(); - } - else - { - //TODO update existing dynamic textures - } - - return LLUUID.Zero.ToString(); - } - - private void NotImplemented(string Command) - { - if (throwErrorOnNotImplemented) - throw new NotImplementedException("Command not implemented: " + Command); - } - - private void LSLError(string msg) - { - throw new Exception("LSL Runtime Error: " + msg); - } - } -} +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Text; +using System.Threading; +using Axiom.Math; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; +//using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; + +namespace OpenSim.Region.ScriptEngine.Common +{ + /// + /// Contains all LSL ll-functions. This class will be in Default AppDomain. + /// + public class LSL_BuiltIn_Commands : MarshalByRefObject, LSL_BuiltIn_Commands_Interface + { + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private ASCIIEncoding enc = new ASCIIEncoding(); + private ScriptEngineBase.ScriptEngine m_ScriptEngine; + private SceneObjectPart m_host; + private uint m_localID; + private LLUUID m_itemID; + private bool throwErrorOnNotImplemented = true; + + public LSL_BuiltIn_Commands(ScriptEngineBase.ScriptEngine ScriptEngine, SceneObjectPart host, uint localID, LLUUID itemID) + { + m_ScriptEngine = ScriptEngine; + m_host = host; + m_localID = localID; + m_itemID = itemID; + + //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]"); + } + + private DateTime m_timer = DateTime.Now; + private string m_state = "default"; + + public string State + { + get { return m_state; } + set { + bool changed = false; + if (m_state != value) + changed = true; + // Set it + m_state = value; + + if (changed) + { + m_ScriptEngine.m_EventManager.state_entry(m_localID); + } + } + } + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("LSL_BuiltIn_Commands: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + public Scene World + { + get { return m_ScriptEngine.World; } + } + + //These are the implementations of the various ll-functions used by the LSL scripts. + //starting out, we use the System.Math library for trig functions. - ckrinke 8-14-07 + public double llSin(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Sin(f); + } + + public double llCos(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Cos(f); + } + + public double llTan(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Tan(f); + } + + public double llAtan2(double x, double y) + { + m_host.AddScriptLPS(1); + return (double)Math.Atan2(y, x); + } + + public double llSqrt(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Sqrt(f); + } + + public double llPow(double fbase, double fexponent) + { + m_host.AddScriptLPS(1); + return (double)Math.Pow(fbase, fexponent); + } + + public int llAbs(int i) + { + m_host.AddScriptLPS(1); + return (int)Math.Abs(i); + } + + public double llFabs(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Abs(f); + } + + public double llFrand(double mag) + { + m_host.AddScriptLPS(1); + lock (Util.RandomClass) + { + return Util.RandomClass.NextDouble() * mag; + } + } + + public int llFloor(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Floor(f); + } + + public int llCeil(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Ceiling(f); + } + + public int llRound(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Round(f, 0); + } + + //This next group are vector operations involving squaring and square root. ckrinke + public double llVecMag(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + return (v.x * v.x + v.y * v.y + v.z * v.z); + } + + public LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + double mag = v.x * v.x + v.y * v.y + v.z * v.z; + LSL_Types.Vector3 nor = new LSL_Types.Vector3(); + nor.x = v.x / mag; + nor.y = v.y / mag; + nor.z = v.z / mag; + return nor; + } + + public double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b) + { + m_host.AddScriptLPS(1); + 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); + } + + //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke + public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke + LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); + double m = (t.x + t.y + t.z + t.s); + if (m == 0) return new LSL_Types.Vector3(); + double n = 2 * (r.y * r.s + r.x * r.z); + double p = m * m - n * n; + if (p > 0) + return new LSL_Types.Vector3(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)), + Math.Atan2(n, Math.Sqrt(p)), + Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))); + else if (n > 0) + return new LSL_Types.Vector3(0.0, Math.PI / 2, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); + else + return new LSL_Types.Vector3(0.0, -Math.PI / 2, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); + } + + public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + //this comes from from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions but is incomplete as of 8/19/07 + float err = 0.00001f; + double ax = Math.Sin(v.x / 2); + double aw = Math.Cos(v.x / 2); + double by = Math.Sin(v.y / 2); + double bw = Math.Cos(v.y / 2); + double cz = Math.Sin(v.z / 2); + double cw = Math.Cos(v.z / 2); + LSL_Types.Quaternion a1 = new LSL_Types.Quaternion(0.0, 0.0, cz, cw); + LSL_Types.Quaternion a2 = new LSL_Types.Quaternion(0.0, by, 0.0, bw); + LSL_Types.Quaternion a3 = new LSL_Types.Quaternion(ax, 0.0, 0.0, aw); + LSL_Types.Quaternion a = (a1 * a2) * a3; + //This multiplication doesnt compile, yet. a = a1 * a2 * a3; + LSL_Types.Quaternion b = new LSL_Types.Quaternion(ax * bw * cw + aw * by * cz, + aw * by * cw - ax * bw * cz, aw * bw * cz + ax * by * cw, + aw * bw * cw - ax * by * cz); + LSL_Types.Quaternion c = new LSL_Types.Quaternion(); + //This addition doesnt compile yet c = a + b; + LSL_Types.Quaternion d = new LSL_Types.Quaternion(); + //This addition doesnt compile yet d = a - b; + if ((Math.Abs(c.x) > err && Math.Abs(d.x) > err) || + (Math.Abs(c.y) > err && Math.Abs(d.y) > err) || + (Math.Abs(c.z) > err && Math.Abs(d.z) > err) || + (Math.Abs(c.s) > err && Math.Abs(d.s) > err)) + { + return b; + //return a new Quaternion that is null until I figure this out + // return b; + // return a; + } + return a; + } + + public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(); + } + + public LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(1,0,0) * r); + } + + public LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(0, 1, 0) * r); + } + + public LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(0, 0, 1) * r); + } + public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 a, LSL_Types.Vector3 b) + { + //A and B should both be normalized + m_host.AddScriptLPS(1); + double dotProduct = LSL_Types.Vector3.Dot(a, b); + LSL_Types.Vector3 crossProduct = LSL_Types.Vector3.Cross(a, b); + double magProduct = LSL_Types.Vector3.Mag(a) * LSL_Types.Vector3.Mag(b); + double angle = Math.Acos(dotProduct / magProduct); + LSL_Types.Vector3 axis = LSL_Types.Vector3.Norm(crossProduct); + double s = Math.Sin(angle / 2); + + return new LSL_Types.Quaternion(axis.x * s, axis.y * s, axis.z * s, (float)Math.Cos(angle / 2)); + } + public void llWhisper(int channelID, string text) + { + m_host.AddScriptLPS(1); + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Whisper, channelID, m_host.Name, text); + } + + public void llSay(int channelID, string text) + { + m_host.AddScriptLPS(1); + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Say, channelID, m_host.Name, text); + } + + public void llShout(int channelID, string text) + { + m_host.AddScriptLPS(1); + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Shout, channelID, m_host.Name, text); + } + + public int llListen(int channelID, string name, string ID, string msg) + { + m_host.AddScriptLPS(1); + if (ID == String.Empty) + { + ID = LLUUID.Zero.ToString(); + } + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, ID, msg); + } + + public void llListenControl(int number, int active) + { + m_host.AddScriptLPS(1); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.ListenControl(number, active); + } + + public void llListenRemove(int number) + { + m_host.AddScriptLPS(1); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.ListenRemove(number); + } + + public void llSensor(string name, string id, int type, double range, double arc) + { + m_host.AddScriptLPS(1); + NotImplemented("llSensor"); + return; + } + + public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) + { + m_host.AddScriptLPS(1); + NotImplemented("llSensorRepeat"); + return; + } + + public void llSensorRemove() + { + m_host.AddScriptLPS(1); + NotImplemented("llSensorRemove"); + return; + } + + public string llDetectedName(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedName"); + return String.Empty; + } + + public string llDetectedKey(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedKey"); + return String.Empty; + } + + public string llDetectedOwner(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedOwner"); + return String.Empty; + } + + public int llDetectedType(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedType"); + return 0; + } + + public LSL_Types.Vector3 llDetectedPos(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedPos"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llDetectedVel(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedVel"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llDetectedGrab(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedGrab"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llDetectedRot(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedRot"); + return new LSL_Types.Quaternion(); + } + + public int llDetectedGroup(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedGroup"); + return 0; + } + + public int llDetectedLinkNumber(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedLinkNumber"); + return 0; + } + + public void llDie() + { + m_host.AddScriptLPS(1); + World.DeleteSceneObjectGroup(m_host.ParentGroup); + return; + } + + public double llGround(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + int x = (int)(m_host.AbsolutePosition.X + offset.x); + int y = (int)(m_host.AbsolutePosition.Y + offset.y); + return World.GetLandHeight(x, y); + } + + public double llCloud(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llCloud"); + return 0; + } + + public LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llWind"); + return new LSL_Types.Vector3(); + } + + public void llSetStatus(int status, int value) + { + m_host.AddScriptLPS(1); + if ((status & LSL_BaseClass.STATUS_PHYSICS) == LSL_BaseClass.STATUS_PHYSICS) + { + m_host.AddFlag(LLObject.ObjectFlags.Physics); + } + if ((status & LSL_BaseClass.STATUS_PHANTOM) == LSL_BaseClass.STATUS_PHANTOM) + { + m_host.AddFlag(LLObject.ObjectFlags.Phantom); + } + if ((status & LSL_BaseClass.STATUS_CAST_SHADOWS) == LSL_BaseClass.STATUS_CAST_SHADOWS) + { + m_host.AddFlag(LLObject.ObjectFlags.CastShadows); + } + if ((status & LSL_BaseClass.STATUS_ROTATE_X) == LSL_BaseClass.STATUS_ROTATE_X) + { + NotImplemented("llSetStatus - STATUS_ROTATE_X"); + } + if ((status & LSL_BaseClass.STATUS_ROTATE_Y) == LSL_BaseClass.STATUS_ROTATE_Y) + { + NotImplemented("llSetStatus - STATUS_ROTATE_Y"); + } + if ((status & LSL_BaseClass.STATUS_ROTATE_Z) == LSL_BaseClass.STATUS_ROTATE_Z) + { + NotImplemented("llSetStatus - STATUS_ROTATE_Z"); + } + if ((status & LSL_BaseClass.STATUS_BLOCK_GRAB) == LSL_BaseClass.STATUS_BLOCK_GRAB) + { + NotImplemented("llSetStatus - STATUS_BLOCK_GRAB"); + } + if ((status & LSL_BaseClass.STATUS_DIE_AT_EDGE) == LSL_BaseClass.STATUS_DIE_AT_EDGE) + { + NotImplemented("llSetStatus - STATUS_DIE_AT_EDGE"); + } + if ((status & LSL_BaseClass.STATUS_RETURN_AT_EDGE) == LSL_BaseClass.STATUS_RETURN_AT_EDGE) + { + NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE"); + } + if ((status & LSL_BaseClass.STATUS_SANDBOX) == LSL_BaseClass.STATUS_SANDBOX) + { + NotImplemented("llSetStatus - STATUS_SANDBOX"); + } + + return; + } + + public int llGetStatus(int status) + { + m_host.AddScriptLPS(1); + Console.WriteLine(m_host.UUID.ToString() + " status is " + m_host.ObjectFlags.ToString()); + switch (status) + { + case LSL_BaseClass.STATUS_PHYSICS: + if ((m_host.ObjectFlags & (uint)LLObject.ObjectFlags.Physics) == (uint)LLObject.ObjectFlags.Physics) + { + return 1; + } + return 0; + case LSL_BaseClass.STATUS_PHANTOM: + if ((m_host.ObjectFlags & (uint)LLObject.ObjectFlags.Phantom) == (uint)LLObject.ObjectFlags.Phantom) + { + return 1; + } + return 0; + case LSL_BaseClass.STATUS_CAST_SHADOWS: + if ((m_host.ObjectFlags & (uint)LLObject.ObjectFlags.CastShadows) == (uint)LLObject.ObjectFlags.CastShadows) + { + return 1; + } + return 0; + case LSL_BaseClass.STATUS_BLOCK_GRAB: + NotImplemented("llGetStatus - STATUS_BLOCK_GRAB"); + return 0; + case LSL_BaseClass.STATUS_DIE_AT_EDGE: + NotImplemented("llGetStatus - STATUS_DIE_AT_EDGE"); + return 0; + case LSL_BaseClass.STATUS_RETURN_AT_EDGE: + NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE"); + return 0; + case LSL_BaseClass.STATUS_ROTATE_X: + NotImplemented("llGetStatus - STATUS_ROTATE_X"); + return 0; + case LSL_BaseClass.STATUS_ROTATE_Y: + NotImplemented("llGetStatus - STATUS_ROTATE_Y"); + return 0; + case LSL_BaseClass.STATUS_ROTATE_Z: + NotImplemented("llGetStatus - STATUS_ROTATE_Z"); + return 0; + case LSL_BaseClass.STATUS_SANDBOX: + NotImplemented("llGetStatus - STATUS_SANDBOX"); + return 0; + } + NotImplemented("llGetStatus - Unknown Status parameter"); + return 0; + } + + public void llSetScale(LSL_Types.Vector3 scale) + { + m_host.AddScriptLPS(1); + // TODO: this needs to trigger a persistance save as well + LLVector3 tmp = m_host.Scale; + tmp.X = (float)scale.x; + tmp.Y = (float)scale.y; + tmp.Z = (float)scale.z; + m_host.Scale = tmp; + m_host.SendFullUpdateToAllClients(); + return; + } + + public LSL_Types.Vector3 llGetScale() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); + } + + public void llSetColor(LSL_Types.Vector3 color, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + m_host.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + } + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llSetColor"); + } + } + + public double llGetAlpha(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color + { + return (double)((tex.DefaultTexture.RGBA.A * 255) / 255); + } + if (face > -1) + { + return (double)((tex.GetFace((uint)face).RGBA.A * 255) / 255); + } + return 0; + } + + public void llSetAlpha(double alpha, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + m_host.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llSetAlpha"); + } + } + + public LSL_Types.Vector3 llGetColor(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LLColor texcolor; + LSL_Types.Vector3 rgb; + if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color + { + texcolor = tex.DefaultTexture.RGBA; + rgb.x = (255 - (texcolor.R * 255)) / 255; + rgb.y = (255 - (texcolor.G * 255)) / 255; + rgb.z = (255 - (texcolor.B * 255)) / 255; + return rgb; + } + if (face > -1) + { + texcolor = tex.GetFace((uint)face).RGBA; + rgb.x = (255 - (texcolor.R * 255)) / 255; + rgb.y = (255 - (texcolor.G * 255)) / 255; + rgb.z = (255 - (texcolor.B * 255)) / 255; + return rgb; + } + else + { + NotImplemented("llGetColor"); + return new LSL_Types.Vector3(); + } + } + + public void llSetTexture(string texture, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.TextureID = new LLUUID(texture); + tex.FaceTextures[face] = texface; + m_host.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].TextureID = new LLUUID(texture); + } + } + tex.DefaultTexture.TextureID = new LLUUID(texture); + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llSetTexture"); + } + } + + public void llScaleTexture(double u, double v, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.RepeatU = (float)u; + texface.RepeatV = (float)v; + tex.FaceTextures[face] = texface; + m_host.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; 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; + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llScaleTexture"); + } + } + + public void llOffsetTexture(double u, double v, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.OffsetU = (float)u; + texface.OffsetV = (float)v; + tex.FaceTextures[face] = texface; + m_host.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; 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; + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llOffsetTexture"); + } + } + + public void llRotateTexture(double rotation, int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.Rotation = (float)rotation; + tex.FaceTextures[face] = texface; + m_host.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].Rotation = (float)rotation; + } + } + tex.DefaultTexture.Rotation = (float)rotation; + m_host.UpdateTexture(tex); + return; + } + else + { + NotImplemented("llRotateTexture"); + } + } + + public string llGetTexture(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) + { + face = 0; + } + if (face > -1) + { + LLObject.TextureEntryFace texface; + texface = tex.GetFace((uint)face); + return texface.TextureID.ToString(); + } + else + { + NotImplemented("llGetTexture"); + return String.Empty; + } + } + + public void llSetPos(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + if (m_host.ParentID != 0) + { + m_host.UpdateOffSet(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); + } + else + { + m_host.UpdateGroupPosition(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); + } + } + + public LSL_Types.Vector3 llGetPos() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + } + + public LSL_Types.Vector3 llGetLocalPos() + { + m_host.AddScriptLPS(1); + if (m_host.ParentID != 0) + { + return new LSL_Types.Vector3(m_host.OffsetPosition.X, + m_host.OffsetPosition.Y, + m_host.OffsetPosition.Z); + } + else + { + return new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + } + } + + public void llSetRot(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + m_host.UpdateRotation(new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s)); + } + + public LSL_Types.Quaternion llGetRot() + { + m_host.AddScriptLPS(1); + LLQuaternion q = m_host.RotationOffset; + return new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + } + + public LSL_Types.Quaternion llGetLocalRot() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); + } + + public void llSetForce(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetForce"); + } + + public LSL_Types.Vector3 llGetForce() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetForce"); + return new LSL_Types.Vector3(); + } + + public int llTarget(LSL_Types.Vector3 position, double range) + { + m_host.AddScriptLPS(1); + NotImplemented("llTarget"); + return 0; + } + + public void llTargetRemove(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llTargetRemove"); + } + + public int llRotTarget(LSL_Types.Quaternion rot, double error) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotTarget"); + return 0; + } + + public void llRotTargetRemove(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotTargetRemove"); + } + + public void llMoveToTarget(LSL_Types.Vector3 target, double tau) + { + m_host.AddScriptLPS(1); + NotImplemented("llMoveToTarget"); + } + + public void llStopMoveToTarget() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopMoveToTarget"); + } + + public void llApplyImpulse(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + //No energy force yet + if (local == 1) + { + NotImplemented("llApplyImpulse Local Force"); + } + else + { + if (force.x > 20000) + force.x = 20000; + if (force.y > 20000) + force.y = 20000; + if (force.z > 20000) + force.z = 20000; + + m_host.ApplyImpulse(new LLVector3((float)force.x,(float)force.y,(float)force.z)); + } + } + + public void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llApplyRotationalImpulse"); + } + + public void llSetTorque(LSL_Types.Vector3 torque, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetTorque"); + } + + public LSL_Types.Vector3 llGetTorque() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetTorque"); + return new LSL_Types.Vector3(); + } + + public void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetForceAndTorque"); + } + + public LSL_Types.Vector3 llGetVel() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z); + } + + public LSL_Types.Vector3 llGetAccel() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); + } + + public LSL_Types.Vector3 llGetOmega() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetOmega"); + return new LSL_Types.Vector3(); + } + + public double llGetTimeOfDay() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetTimeOfDay"); + return 0; + } + + public double llGetWallclock() + { + m_host.AddScriptLPS(1); + return DateTime.Now.TimeOfDay.TotalSeconds; + } + + public double llGetTime() + { + m_host.AddScriptLPS(1); + TimeSpan ScriptTime = DateTime.Now - m_timer; + return (double)(ScriptTime.TotalMilliseconds / 1000); + } + + public void llResetTime() + { + m_host.AddScriptLPS(1); + m_timer = DateTime.Now; + } + + public double llGetAndResetTime() + { + m_host.AddScriptLPS(1); + TimeSpan ScriptTime = DateTime.Now - m_timer; + m_timer = DateTime.Now; + return (double)(ScriptTime.TotalMilliseconds / 1000); + } + + public void llSound() + { + m_host.AddScriptLPS(1); + // This function has been deprecated + // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound + NotImplemented("llSound"); + } + + public void llPlaySound(string sound, double volume) + { + m_host.AddScriptLPS(1); + m_host.SendSound(sound, volume, false); + } + + public void llLoopSound(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llLoopSound"); + } + + public void llLoopSoundMaster(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llLoopSoundMaster"); + } + + public void llLoopSoundSlave(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llLoopSoundSlave"); + } + + public void llPlaySoundSlave(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llPlaySoundSlave"); + } + + public void llTriggerSound(string sound, double volume) + { + m_host.AddScriptLPS(1); + m_host.SendSound(sound, volume, true); + } + + public void llStopSound() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopSound"); + } + + public void llPreloadSound(string sound) + { + m_host.AddScriptLPS(1); + m_host.PreloadSound(sound); + } + + public string llGetSubString(string src, int start, int end) + { + m_host.AddScriptLPS(1); + // substring expects length + // return src.Substring(start, end); + + // if one is negative so use length of string as base + // if start > end then it is exclusive + // for length add +1 for char at location=0 + if (start < 0) { start = src.Length-start; } + if (end < 0) { end = src.Length - end; } + if (start > end) + { + return src.Substring(0, 1+end) + src.Substring(start, src.Length - start); + } + else + { + return src.Substring(start, (1+end) - start); + } + } + + public string llDeleteSubString(string src, int start, int end) + { + m_host.AddScriptLPS(1); + //return src.Remove(start, end - start); + // if one is negative so use length of string as base + // if start > end then it is exclusive + // for length add +1 for char at location=0 + if (start < 0) { start = src.Length - start; } + if (end < 0) { end = src.Length - end; } + if (start > end) + { + return src.Remove(0, 1 + end) + src.Remove(start, src.Length - start); + } + else + { + return src.Remove(start, (1 + end) - start); + } + } + + + public string llInsertString(string dst, int position, string src) + { + m_host.AddScriptLPS(1); + return dst.Insert(position, src); + } + + public string llToUpper(string src) + { + m_host.AddScriptLPS(1); + return src.ToUpper(); + } + + public string llToLower(string src) + { + m_host.AddScriptLPS(1); + return src.ToLower(); + } + + public int llGiveMoney(string destination, int amount) + { + m_host.AddScriptLPS(1); + NotImplemented("llGiveMoney"); + return 0; + } + + public void llMakeExplosion() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeExplosion"); + } + + public void llMakeFountain() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeFountain"); + } + + public void llMakeSmoke() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeSmoke"); + } + + public void llMakeFire() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeFire"); + } + + public void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Quaternion rot, int param) + { + m_host.AddScriptLPS(1); + NotImplemented("llRezObject"); + } + + public void llLookAt(LSL_Types.Vector3 target, double strength, double damping) + { + m_host.AddScriptLPS(1); + NotImplemented("llLookAt"); + } + + public void llStopLookAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopLookAt"); + } + + public void llSetTimerEvent(double sec) + { + m_host.AddScriptLPS(1); + // Setting timer repeat + m_ScriptEngine.m_ASYNCLSLCommandManager.SetTimerEvent(m_localID, m_itemID, sec); + } + + public void llSleep(double sec) + { + m_host.AddScriptLPS(1); + Thread.Sleep((int)(sec * 1000)); + } + + public double llGetMass() + { + m_host.AddScriptLPS(1); + return m_host.GetMass(); + } + + public void llCollisionFilter(string name, string id, int accept) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionFilter"); + } + + public void llTakeControls(int controls, int accept, int pass_on) + { + m_host.AddScriptLPS(1); + NotImplemented("llTakeControls"); + } + + public void llReleaseControls() + { + m_host.AddScriptLPS(1); + NotImplemented("llReleaseControls"); + } + + public void llAttachToAvatar(int attachment) + { + m_host.AddScriptLPS(1); + NotImplemented("llAttachToAvatar"); + } + + public void llDetachFromAvatar() + { + m_host.AddScriptLPS(1); + NotImplemented("llDetachFromAvatar"); + } + + public void llTakeCamera() + { + m_host.AddScriptLPS(1); + NotImplemented("llTakeCamera"); + } + + public void llReleaseCamera() + { + m_host.AddScriptLPS(1); + NotImplemented("llReleaseCamera"); + } + + public string llGetOwner() + { + m_host.AddScriptLPS(1); + return m_host.ObjectOwner.ToString(); + } + + public void llInstantMessage(string user, string message) + { + m_host.AddScriptLPS(1); + NotImplemented("llInstantMessage"); + + // 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.) + + // 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()); + } + + public void llEmail(string address, string subject, string message) + { + m_host.AddScriptLPS(1); + NotImplemented("llEmail"); + } + + public void llGetNextEmail(string address, string subject) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetNextEmail"); + } + + public string llGetKey() + { + m_host.AddScriptLPS(1); + return m_host.UUID.ToString(); + } + + public void llSetBuoyancy(double buoyancy) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetBuoyancy"); + } + + public void llSetHoverHeight(double height, int water, double tau) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetHoverHeight"); + } + + public void llStopHover() + { + m_host.AddScriptLPS(1); + m_host.AddScriptLPS(1); + NotImplemented("llStopHover"); + } + + public void llMinEventDelay(double delay) + { + m_host.AddScriptLPS(1); + NotImplemented("llMinEventDelay"); + } + + public void llSoundPreload() + { + m_host.AddScriptLPS(1); + NotImplemented("llSoundPreload"); + } + + public void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotLookAt"); + } + + public int 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); + NotImplemented("llStartAnimation"); + } + + public void llStopAnimation(string anim) + { + m_host.AddScriptLPS(1); + NotImplemented("llStopAnimation"); + } + + public void llPointAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llPointAt"); + } + + public void llStopPointAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopPointAt"); + } + + public void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain) + { + m_host.AddScriptLPS(1); + m_host.RotationalVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); + m_host.AngularVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); + m_host.ScheduleTerseUpdate(); + m_host.SendTerseUpdateToAllClients(); + //NotImplemented("llTargetOmega"); + } + + public int llGetStartParameter() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetStartParameter"); + return 0; + } + + public void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llGodLikeRezObject"); + } + + public void llRequestPermissions(string agent, int perm) + { + m_host.AddScriptLPS(1); + NotImplemented("llRequestPermissions"); + } + + public string llGetPermissionsKey() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetPermissionsKey"); + return String.Empty; + } + + public int llGetPermissions() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetPermissions"); + return 0; + } + + public int llGetLinkNumber() + { + m_host.AddScriptLPS(1); + return m_host.LinkNum; + } + + public void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); + if (linknumber > -1) + { + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + return; + } + else if (linknumber == -1) + { + int num = m_host.ParentGroup.PrimCount; + for (int w = 0; w < num; w++) + { + linknumber = w; + part = m_host.ParentGroup.GetLinkNumPart(linknumber); + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + } + } + return; + } + else + { + NotImplemented("llSetLinkColor"); + } + } + + public void llCreateLink(string target, int parent) + { + m_host.AddScriptLPS(1); + NotImplemented("llCreateLink"); + } + + public void llBreakLink(int linknum) + { + m_host.AddScriptLPS(1); + NotImplemented("llBreakLink"); + } + + public void llBreakAllLinks() + { + m_host.AddScriptLPS(1); + NotImplemented("llBreakAllLinks"); + } + + public string llGetLinkKey(int linknum) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); + if (part != null) + { + return part.UUID.ToString(); + } + else + { + return "00000000-0000-0000-0000-000000000000"; + } + } + + public string llGetLinkName(int linknum) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); + if (part != null) + { + return part.Name; + } + else + { + return "00000000-0000-0000-0000-000000000000"; + } + } + + public int llGetInventoryNumber(int type) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryNumber"); + return 0; + } + + public string llGetInventoryName(int type, int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryName"); + return String.Empty; + } + + public void llSetScriptState(string name, int run) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetScriptState"); + } + + public double llGetEnergy() + { + m_host.AddScriptLPS(1); + return 1.0f; + } + + public void llGiveInventory(string destination, string inventory) + { + m_host.AddScriptLPS(1); + NotImplemented("llGiveInventory"); + } + + public void llRemoveInventory(string item) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveInventory"); + } + + public void llSetText(string text, LSL_Types.Vector3 color, double alpha) + { + m_host.AddScriptLPS(1); + Vector3 av3 = new Vector3((float)color.x, (float)color.y, (float)color.z); + m_host.SetText(text, av3, alpha); + } + + public double llWater(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + return World.RegionInfo.EstateSettings.waterHeight; + } + + public void llPassTouches(int pass) + { + m_host.AddScriptLPS(1); + NotImplemented("llPassTouches"); + } + + public string llRequestAgentData(string id, int data) + { + m_host.AddScriptLPS(1); + NotImplemented("llRequestAgentData"); + return String.Empty; + } + + public string llRequestInventoryData(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llRequestInventoryData"); + return String.Empty; + } + + public void llSetDamage(double damage) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetDamage"); + } + + public void llTeleportAgentHome(string agent) + { + m_host.AddScriptLPS(1); + NotImplemented("llTeleportAgentHome"); + } + + public void llModifyLand(int action, int brush) + { + m_host.AddScriptLPS(1); + double dsize; + if (World.PermissionsMngr.CanTerraform(m_host.OwnerID, new LLVector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0))) + { + switch (brush) + { + case 1: + dsize = 2; + break; + case 2: + dsize = 4; + break; + case 3: + dsize = 8; + break; + default: + if (brush < 0) + { + dsize = (double)(-1 * brush); + } + else + { + LSLError("Invalid brush size"); + dsize = 0; // Should cease execution, but get unassigned local variable dsize on compile. + } + break; + } + switch (action) + { + case 0: + if (World.Terrain.GetHeight((int)m_host.AbsolutePosition.X, (int)m_host.AbsolutePosition.Y) < m_host.AbsolutePosition.Z) + { + World.Terrain.FlattenTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + } + break; + case 1: + if (World.Terrain.GetHeight((int)m_host.AbsolutePosition.X, (int)m_host.AbsolutePosition.Y) < (double)m_host.AbsolutePosition.Z) + { + World.Terrain.RaiseTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 0.1); + } + break; + case 2: + if (World.Terrain.GetHeight((int)m_host.AbsolutePosition.X, (int)m_host.AbsolutePosition.Y) > 0) + { + World.Terrain.LowerTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + } + break; + case 3: + World.Terrain.SmoothTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + break; + case 4: + World.Terrain.NoiseTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + break; + case 5: + World.Terrain.RevertTerrain(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, dsize, 1); + break; + default: + break; + } + } + } + + public void llCollisionSound(string impact_sound, double impact_volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionSound"); + } + + public void llCollisionSprite(string impact_sprite) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionSprite"); + } + + public string llGetAnimation(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAnimation"); + return String.Empty; + } + + public void llResetScript() + { + m_host.AddScriptLPS(1); + m_ScriptEngine.m_ScriptManager.ResetScript(m_localID, m_itemID); + } + + public void llMessageLinked(int linknum, int num, string str, string id) + { + m_host.AddScriptLPS(1); + } + + public void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local) + { + m_host.AddScriptLPS(1); + } + + public void llPassCollisions(int pass) + { + m_host.AddScriptLPS(1); + } + + public string llGetScriptName() + { + m_host.AddScriptLPS(1); + return String.Empty; + } + + public int llGetNumberOfSides() + { + m_host.AddScriptLPS(1); + return 0; + } + + public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle) + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(); + } + + public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(); + } + + public void llRot2Angle() + { + m_host.AddScriptLPS(1); + } + + public double llAcos(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Acos(val); + } + + public double llAsin(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Asin(val); + } + + public double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b) + { + m_host.AddScriptLPS(1); + return 0; + } + + public string llGetInventoryKey(string name) + { + m_host.AddScriptLPS(1); + return String.Empty; + } + + public void llAllowInventoryDrop(int add) + { + m_host.AddScriptLPS(1); + } + + public LSL_Types.Vector3 llGetSunDirection() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGetTextureOffset(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LSL_Types.Vector3 offset; + if (face == -1) + { + face = 0; + } + offset.x = tex.GetFace((uint)face).OffsetU; + offset.y = tex.GetFace((uint)face).OffsetV; + offset.z = 0.0; + return offset; + } + + public LSL_Types.Vector3 llGetTextureScale(int side) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LSL_Types.Vector3 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 double llGetTextureRot(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) + { + face = 0; + } + return tex.GetFace((uint)face).Rotation; + } + + public int llSubStringIndex(string source, string pattern) + { + m_host.AddScriptLPS(1); + return source.IndexOf(pattern); + } + + public string llGetOwnerKey(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetOwnerKey"); + return String.Empty; + } + + public LSL_Types.Vector3 llGetCenterOfMass() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCenterOfMass"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending) + { + m_host.AddScriptLPS(1); + // SortedList sorted = new SortedList(); + // Add chunks to an array + //int s = stride; + //if (s < 1) + // s = 1; + //int c = 0; + //LSL_Types.list chunk = new LSL_Types.list(); + //string chunkString = String.Empty; + //foreach (string element in src) + //{ + // c++; + // if (c > s) + // { + // sorted.Add(chunkString, chunk); + // chunkString = String.Empty; + // chunk = new LSL_Types.list(); + // c = 0; + // } + // chunk.Add(element); + // chunkString += element.ToString(); + //} + //if (chunk.Count > 0) + // sorted.Add(chunkString, chunk); + + //LSL_Types.list ret = new LSL_Types.list(); + //foreach (LSL_Types.list ls in sorted.Values) + //{ + // ret.AddRange(ls); + //} + + //if (ascending == LSL_BaseClass.TRUE) + // return ret; + //ret.Reverse(); + //return ret; + NotImplemented("llListSort"); + return new LSL_Types.list(); + } + + public int llGetListLength(LSL_Types.list src) + { + m_host.AddScriptLPS(1); + return src.Length; + } + + public int llList2Integer(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0; + } + return Convert.ToInt32(src.Data[index]); + } + + public double osList2Double(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0.0; + } + return Convert.ToDouble(src.Data[index]); + } + + public double llList2Float(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0.0; + } + return Convert.ToDouble(src.Data[index]); + } + + public string llList2String(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return String.Empty; + } + return src.Data[index].ToString(); + } + + public string llList2Key(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return "00000000-0000-0000-0000-000000000000"; + } + //return OpenSim.Framework.ToString(src[index]); + LLUUID tmpkey; + if (LLUUID.TryParse(src.Data[index].ToString(), out tmpkey)) + { + return tmpkey.ToString(); + } + else + { + return "00000000-0000-0000-0000-000000000000"; + } + } + + public LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return new LSL_Types.Vector3(0, 0, 0); + } + if (src.Data[index].GetType() == typeof(OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3)) + { + return (LSL_Types.Vector3)src.Data[index]; + } + else + { + return new LSL_Types.Vector3(0, 0, 0); + } + } + + public LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return new LSL_Types.Quaternion(0, 0, 0, 1); + } + if (src.Data[index].GetType() == typeof(OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion)) + { + return (LSL_Types.Quaternion)src.Data[index]; + } + else + { + return new LSL_Types.Quaternion(0, 0, 0, 1); + } + } + + public LSL_Types.list llList2List(LSL_Types.list src, int start, int end) + { + m_host.AddScriptLPS(1); + return src.GetSublist(start, end); + } + + public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end) + { + //LSL_Types.list ret = new LSL_Types.list(src); + //ret.RemoveRange(start, end - start); + //return ret; + + // Just a hunch - needs testing + return src.GetSublist(end, start); + } + + public int llGetListEntryType(LSL_Types.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 System.Int32) + return 1; + if (src.Data[index] is System.Double) + return 2; + if (src.Data[index] is System.String) + { + LLUUID tuuid; + if (LLUUID.TryParse(src.Data[index].ToString(), out tuuid)) + { + return 3; + } + else + { + return 4; + } + } + if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3) + return 5; + if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion) + return 6; + if (src.Data[index] is OpenSim.Region.ScriptEngine.Common.LSL_Types.list) + return 7; + return 0; + + } + + public string llList2CSV(LSL_Types.list src) + { + m_host.AddScriptLPS(1); + string ret = String.Empty; + foreach (object o in src.Data) + { + ret = ret + o.ToString() + ", "; + } + ret = ret.Substring(0, ret.Length - 2); + return ret; + } + + public LSL_Types.list llCSV2List(string src) + { + m_host.AddScriptLPS(1); + return new LSL_Types.list(src.Split(",".ToCharArray())); + } + + public LSL_Types.list llListRandomize(LSL_Types.list src, int stride) + { + m_host.AddScriptLPS(1); + //int s = stride; + //if (s < 1) + // s = 1; + + // This is a cowardly way of doing it ;) + // TODO: Instead, randomize and check if random is mod stride or if it can not be, then array.removerange + //List tmp = new List(); + + // Add chunks to an array + //int c = 0; + //LSL_Types.list chunk = new LSL_Types.list(); + //foreach (string element in src) + //{ + // c++; + // if (c > s) + // { + // tmp.Add(chunk); + // chunk = new LSL_Types.list(); + // c = 0; + // } + // chunk.Add(element); + //} + //if (chunk.Count > 0) + // tmp.Add(chunk); + + // Decreate (<- what kind of word is that? :D ) array back into a list + //int rnd; + //LSL_Types.list ret = new LSL_Types.list(); + //while (tmp.Count > 0) + //{ + // rnd = Util.RandomClass.Next(tmp.Count); + // foreach (string str in tmp[rnd]) + // { + // ret.Add(str); + // } + // tmp.RemoveAt(rnd); + //} + + //return ret; + NotImplemented("llListRandomize"); + return src; + } + + public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride) + { + m_host.AddScriptLPS(1); + LSL_Types.list ret = new LSL_Types.list(); + //int s = stride; + //if (s < 1) + // s = 1; + + //int sc = s; + //for (int i = start; i < src.Count; i++) + //{ + // sc--; + // if (sc == 0) + // { + // sc = s; + // // Addthis + // ret.Add(src[i]); + // } + // if (i == end) + // break; + //} + NotImplemented("llList2ListStrided"); + return ret; + } + + public LSL_Types.Vector3 llGetRegionCorner() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0); + } + + public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start) + { + m_host.AddScriptLPS(1); + return dest.GetSublist(0, start - 1) + src + dest.GetSublist(start, -1); + } + + public int llListFindList(LSL_Types.list src, LSL_Types.list test) + { + m_host.AddScriptLPS(1); + //foreach (string s in test) + //{ + // for (int ci = 0; ci < src.Count; ci++) + // { + // if (s == src[ci]) + // return ci; + // } + //} + NotImplemented("llListFindList"); + return -1; + } + + public string llGetObjectName() + { + m_host.AddScriptLPS(1); + return m_host.Name; + } + + public void llSetObjectName(string name) + { + m_host.AddScriptLPS(1); + m_host.Name = name; + } + + public string llGetDate() + { + m_host.AddScriptLPS(1); + DateTime date = DateTime.Now.ToUniversalTime(); + string result = date.ToString("yyyy-MM-dd"); + return result; + } + + public int llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir) + { + m_host.AddScriptLPS(1); + NotImplemented("llEdgeOfWorld"); + return 0; + } + + public int llGetAgentInfo(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAgentInfo"); + return 0; + } + + public void llAdjustSoundVolume(double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llAdjustSoundVolume"); + } + + public void llSetSoundQueueing(int queue) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetSoundQueueing"); + } + + public void llSetSoundRadius(double radius) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetSoundRadius"); + } + + public string llKey2Name(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llKey2Name"); + return String.Empty; + } + + + + public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_host.AddScriptLPS(1); + Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); + pTexAnim.Flags =(uint) mode; + + //ALL_SIDES + if (face == -1) + face = 255; + + pTexAnim.Face = (uint)face; + pTexAnim.Length = (float)length; + pTexAnim.Rate = (float)rate; + pTexAnim.SizeX = (uint)sizex; + pTexAnim.SizeY = (uint)sizey; + pTexAnim.Start = (float)start; + + m_host.AddTextureAnimation(pTexAnim); + m_host.SendFullUpdateToAllClients(); + } + + public void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, + LSL_Types.Vector3 bottom_south_west) + { + m_host.AddScriptLPS(1); + NotImplemented("llTriggerSoundLimited"); + } + + public void llEjectFromLand(string pest) + { + m_host.AddScriptLPS(1); + NotImplemented("llEjectFromLand"); + } + + public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers) + { + m_host.AddScriptLPS(1); + LSL_Types.list ret = new LSL_Types.list(); + object[] delimeters = new object[separators.Length + spacers.Length]; + separators.Data.CopyTo(delimeters, 0); + spacers.Data.CopyTo(delimeters, separators.Length); + bool dfound = false; + do + { + dfound = false; + int cindex = -1; + string cdeli = ""; + for (int i = 0; i < delimeters.Length; i++) + { + int index = str.IndexOf(delimeters[i].ToString()); + bool found = index != -1; + if (found) + { + if ((cindex > index) || (cindex == -1)) + { + cindex = index; + cdeli = (string)delimeters[i]; + } + dfound = dfound || found; + } + } + if (cindex != -1) + { + if (cindex > 0) + { + ret.Add(str.Substring(0, cindex)); + if (spacers.Contains(cdeli)) + { + ret.Add(cdeli); + } + } + if (cindex == 0 && spacers.Contains(cdeli)) + { + ret.Add(cdeli); + } + str = str.Substring(cindex + 1); + } + } + while (dfound); + if (str != "") + { + ret.Add(str); + } + return ret; + } + + public int llOverMyLand(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llOverMyLand"); + return 0; + } + + public string llGetLandOwnerAt(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + return World.GetLandOwner((float)pos.x, (float)pos.y).ToString(); + } + + public string llGetNotecardLine(string name, int line) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetNotecardLine"); + return String.Empty; + } + + public LSL_Types.Vector3 llGetAgentSize(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAgentSize"); + return new LSL_Types.Vector3(); + } + + public int llSameGroup(string agent) + { + m_host.AddScriptLPS(1); + NotImplemented("llSameGroup"); + return 0; + } + + public void llUnSit(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llUnSit"); + } + + public LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundSlope"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundNormal"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundContour"); + return new LSL_Types.Vector3(); + } + + public int llGetAttached() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAttached"); + return 0; + } + + public int llGetFreeMemory() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetFreeMemory"); + return 0; + } + + public string llGetRegionName() + { + m_host.AddScriptLPS(1); + return World.RegionInfo.RegionName; + } + + public double llGetRegionTimeDilation() + { + m_host.AddScriptLPS(1); + return (double)World.TimeDilation; + } + + public double llGetRegionFPS() + { + m_host.AddScriptLPS(1); + return 10.0f; + } + + /* 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, + 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; + } + + // AL: This does not actually do anything yet. There are issues within Libsecondlife revolving around PSYS_PART_FLAGS + // (need to OR the values, but currently stores this within an enum) as well as discovery of how the CRC works and the + // actual packet. + + public void llParticleSystem(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); + LSL_Types.Vector3 tempv = new LSL_Types.Vector3(); + + float tempf = 0; + + for (int i = 0; i < rules.Length; i += 2) + { + switch ((int)rules.Data[i]) + { + case (int)LSL_BaseClass.PSYS_PART_FLAGS: + prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)((uint)Convert.ToInt32(rules.Data[i + 1].ToString())); + break; + + case (int)LSL_BaseClass.PSYS_PART_START_COLOR: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartStartColor.R = (float)tempv.x; + prules.PartStartColor.G = (float)tempv.y; + prules.PartStartColor.B = (float)tempv.z; + break; + + case (int)LSL_BaseClass.PSYS_PART_START_ALPHA: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartStartColor.A = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_PART_END_COLOR: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + //prules.PartEndColor = new LLColor(tempv.x,tempv.y,tempv.z,1); + + prules.PartEndColor.R = (float)tempv.x; + prules.PartEndColor.G = (float)tempv.y; + prules.PartEndColor.B = (float)tempv.z; + break; + + case (int)LSL_BaseClass.PSYS_PART_END_ALPHA: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartEndColor.A = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_PART_START_SCALE: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartStartScaleX = (float)tempv.x; + prules.PartStartScaleY = (float)tempv.y; + break; + + case (int)LSL_BaseClass.PSYS_PART_END_SCALE: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartEndScaleX = (float)tempv.x; + prules.PartEndScaleY = (float)tempv.y; + break; + + case (int)LSL_BaseClass.PSYS_PART_MAX_AGE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartMaxAge = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_ACCEL: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartAcceleration.X = (float)tempv.x; + prules.PartAcceleration.Y = (float)tempv.y; + prules.PartAcceleration.Z = (float)tempv.z; + break; + + case (int)LSL_BaseClass.PSYS_SRC_PATTERN: + int tmpi = (int)rules.Data[i + 1]; + prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; + break; + + case (int)LSL_BaseClass.PSYS_SRC_TEXTURE: + prules.Texture = new LLUUID(rules.Data[i + 1].ToString()); + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_RATE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstRate = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_PART_COUNT: + prules.BurstPartCount = (byte)Convert.ToByte(rules.Data[i + 1].ToString()); + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_RADIUS: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstRadius = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_SPEED_MIN: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstSpeedMin = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_BURST_SPEED_MAX: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstSpeedMax = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_MAX_AGE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.MaxAge = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_TARGET_KEY: + LLUUID key = LLUUID.Zero; + if (LLUUID.TryParse(rules.Data[i + 1].ToString(), out key)) + { + prules.Target = key; + } + else + { + prules.Target = m_host.UUID; + } + break; + + case (int)LSL_BaseClass.PSYS_SRC_OMEGA: + // AL: This is an assumption, since it is the only thing that would match. + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.AngularVelocity.X = (float)tempv.x; + prules.AngularVelocity.Y = (float)tempv.y; + prules.AngularVelocity.Z = (float)tempv.z; + //cast?? prules.MaxAge = (float)rules[i + 1]; + break; + + case (int)LSL_BaseClass.PSYS_SRC_ANGLE_BEGIN: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.InnerAngle = (float)tempf; + break; + + case (int)LSL_BaseClass.PSYS_SRC_ANGLE_END: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.OuterAngle = (float)tempf; + break; + } + + } + prules.CRC = 1; + + m_host.AddNewParticleSystem(prules); + m_host.SendFullUpdateToAllClients(); + } + + public void llGroundRepel(double height, int water, double tau) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundRepel"); + } + + public void llGiveInventoryList() + { + m_host.AddScriptLPS(1); + NotImplemented("llGiveInventoryList"); + } + + public void llSetVehicleType(int type) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleType"); + } + + public void llSetVehicledoubleParam(int param, double value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicledoubleParam"); + } + + public void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleVectorParam"); + } + + public void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleRotationParam"); + } + + public void llSetVehicleFlags(int flags) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleFlags"); + } + + public void llRemoveVehicleFlags(int flags) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveVehicleFlags"); + } + + public void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + // LSL quaternions can normalize to 0, normal Quaternions can't. + if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) + rot.z = 1; // ZERO_ROTATION = 0,0,0,1 + + m_host.SetSitTarget(new Vector3((float)offset.x, (float)offset.y, (float)offset.z), new Quaternion((float)rot.s, (float)rot.x, (float)rot.y, (float)rot.z)); + } + + public string llAvatarOnSitTarget() + { + m_host.AddScriptLPS(1); + LLUUID AVID = m_host.GetAvatarOnSitTarget(); + + if (AVID != LLUUID.Zero) + return AVID.ToString(); + else + return String.Empty; + } + + public void llAddToLandPassList(string avatar, double hours) + { + m_host.AddScriptLPS(1); + NotImplemented("llAddToLandPassList"); + } + + 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_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraEyeOffset"); + } + + public void llSetCameraAtOffset(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraAtOffset"); + } + + public string llDumpList2String(LSL_Types.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 void llScriptDanger(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llScriptDanger"); + } + + public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel) + { + m_host.AddScriptLPS(1); + LLUUID av = new LLUUID(); + if (!LLUUID.TryParse(avatar,out av)) + { + LSLError("First parameter to llDialog needs to be a key"); + return; + } + string[] buts = new string[buttons.Length]; + for(int i = 0; i < buttons.Length; i++) + { + buts[i] = buttons.Data[i].ToString(); + } + World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new LLUUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); + //NotImplemented("llDialog"); + } + + public void llVolumeDetect(int detect) + { + m_host.AddScriptLPS(1); + NotImplemented("llVolumeDetect"); + } + + public void llResetOtherScript(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llResetOtherScript"); + } + + public int llGetScriptState(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetScriptState"); + return 0; + } + + public void llRemoteLoadScript() + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoteLoadScript"); + } + + public void llSetRemoteScriptAccessPin(int pin) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetRemoteScriptAccessPin"); + } + + public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoteLoadScriptPin"); + } + + // remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) + // Not sure where these constants should live: + // REMOTE_DATA_CHANNEL = 1 + // REMOTE_DATA_REQUEST = 2 + // REMOTE_DATA_REPLY = 3 + public void llOpenRemoteDataChannel() + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + if (xmlrpcMod.IsEnabled()) + { + LLUUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID); + object[] resobj = new object[] { 1, channelID.ToString(), LLUUID.Zero.ToString(), String.Empty, 0, String.Empty }; + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(m_localID, m_itemID, "remote_data", EventQueueManager.llDetectNull, resobj); + } + } + + public string llSendRemoteData(string channel, string dest, int idata, string sdata) + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString(); + } + + public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); + } + + public void llCloseRemoteDataChannel(string channel) + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpcMod.CloseXMLRPCChannel(channel); + } + + public string llMD5String(string src, int nonce) + { + m_host.AddScriptLPS(1); + return Util.Md5Hash(src + ":" + nonce.ToString()); + } + + public void llSetPrimitiveParams(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetPrimitiveParams"); + } + + public string llStringToBase64(string str) + { + m_host.AddScriptLPS(1); + try + { + byte[] encData_byte = new byte[str.Length]; + encData_byte = Encoding.UTF8.GetBytes(str); + string encodedData = Convert.ToBase64String(encData_byte); + return encodedData; + } + catch (Exception e) + { + throw new Exception("Error in base64Encode" + e.Message); + } + } + + public string llBase64ToString(string str) + { + m_host.AddScriptLPS(1); + UTF8Encoding encoder = new UTF8Encoding(); + Decoder utf8Decode = encoder.GetDecoder(); + try + { + byte[] todecode_byte = Convert.FromBase64String(str); + int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); + char[] decoded_char = new char[charCount]; + utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); + string result = new String(decoded_char); + return result; + } + catch (Exception e) + { + throw new Exception("Error in base64Decode" + e.Message); + } + } + + public void llXorBase64Strings() + { + m_host.AddScriptLPS(1); + throw new Exception("Command deprecated! Use llXorBase64StringsCorrect instead."); + } + + public void llRemoteDataSetRegion() + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoteDataSetRegion"); + } + + public double llLog10(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Log10(val); + } + + public double llLog(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Log(val); + } + + public LSL_Types.list llGetAnimationList(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAnimationList"); + return new LSL_Types.list(); + } + + public void llSetParcelMusicURL(string url) + { + m_host.AddScriptLPS(1); + LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + if (landowner.Equals(null)) + { + return; + } + if (landowner != m_host.ObjectOwner) + { + return; + } + World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); + } + + public LSL_Types.Vector3 llGetRootPosition() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z); + } + + public LSL_Types.Quaternion llGetRootRotation() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W); + } + + public string llGetObjectDesc() + { + return m_host.Description; + } + + public void llSetObjectDesc(string desc) + { + m_host.AddScriptLPS(1); + m_host.Description = desc; + } + + public string llGetCreator() + { + m_host.AddScriptLPS(1); + return m_host.ObjectCreator.ToString(); + } + + public string llGetTimestamp() + { + m_host.AddScriptLPS(1); + return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); + } + + public void llSetLinkAlpha(int linknumber, double alpha, int face) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); + if (linknumber > -1) + { + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + return; + } + else if (linknumber == -1) + { + int num = m_host.ParentGroup.PrimCount; + for (int w = 0; w < num; w++) + { + linknumber = w; + part = m_host.ParentGroup.GetLinkNumPart(linknumber); + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + } + } + return; + } + else + { + NotImplemented("llSetLinkAlpha"); + } + } + + public int llGetNumberOfPrims() + { + m_host.AddScriptLPS(1); + return m_host.ParentGroup.PrimCount; + } + + public string llGetNumberOfNotecardLines(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetNumberOfNotecardLines"); + return String.Empty; + } + + public LSL_Types.list llGetBoundingBox(string obj) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetBoundingBox"); + return new LSL_Types.list(); + } + + public LSL_Types.Vector3 llGetGeometricCenter() + { + return new LSL_Types.Vector3(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); + } + + public void llGetPrimitiveParams() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetPrimitiveParams"); + } + + public string llIntegerToBase64(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llIntegerToBase64"); + return String.Empty; + } + + public int llBase64ToInteger(string str) + { + m_host.AddScriptLPS(1); + NotImplemented("llBase64ToInteger"); + return 0; + } + + public double llGetGMTclock() + { + m_host.AddScriptLPS(1); + return DateTime.UtcNow.TimeOfDay.TotalSeconds; + } + + public string llGetSimulatorHostname() + { + m_host.AddScriptLPS(1); + return System.Environment.MachineName; + } + + public void llSetLocalRot(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + m_host.RotationOffset = new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + } + + public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers) + { + m_host.AddScriptLPS(1); + NotImplemented("llParseStringKeepNulls"); + return new LSL_Types.list(); + } + + public void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, + LSL_Types.Quaternion rot, int param) + { + m_host.AddScriptLPS(1); + NotImplemented("llRezAtRoot"); + } + + public int llGetObjectPermMask(int mask) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetObjectPermMask"); + return 0; + } + + public void llSetObjectPermMask(int mask, int value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetObjectPermMask"); + } + + public void llGetInventoryPermMask(string item, int mask) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryPermMask"); + } + + public void llSetInventoryPermMask(string item, int mask, int value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetInventoryPermMask"); + } + + public string llGetInventoryCreator(string item) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryCreator"); + return String.Empty; + } + + public void llOwnerSay(string msg) + { + m_host.AddScriptLPS(1); + //temp fix so that lsl wiki examples aren't annoying to use to test other functions + World.SimChat(Helpers.StringToField(msg), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Say, 0, m_host.Name, msg); + } + + public void llRequestSimulatorData(string simulator, int data) + { + m_host.AddScriptLPS(1); + NotImplemented("llRequestSimulatorData"); + } + + public void llForceMouselook(int mouselook) + { + m_host.AddScriptLPS(1); + NotImplemented("llForceMouselook"); + } + + public double llGetObjectMass(string id) + { + m_host.AddScriptLPS(1); + LLUUID key = new LLUUID(); + if (LLUUID.TryParse(id,out key)) + { + return (double)World.GetSceneObjectPart(World.Entities[key].LocalId).GetMass(); + } + return 0; + } + + public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end) + { + m_host.AddScriptLPS(1); + return dest.GetSublist(0, start - 1) + src + dest.GetSublist(end + 1, -1); + } + + public void llLoadURL(string avatar_id, string message, string url) + { + m_host.AddScriptLPS(1); + LLUUID avatarId = new LLUUID(avatar_id); + m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message, + url); + } + + public void llParcelMediaCommandList(LSL_Types.list commandList) + { + m_host.AddScriptLPS(1); + NotImplemented("llParcelMediaCommandList"); + } + + public void llParcelMediaQuery() + { + m_host.AddScriptLPS(1); + NotImplemented("llParcelMediaQuery"); + } + + public int llModPow(int a, int b, int c) + { + m_host.AddScriptLPS(1); + Int64 tmp = 0; + Int64 val = Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); + return Convert.ToInt32(tmp); + } + + public int llGetInventoryType(string name) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetInventoryType"); + return 0; + } + + public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetPayPrice"); + } + + public LSL_Types.Vector3 llGetCameraPos() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCameraPos"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llGetCameraRot() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCameraRot"); + return new LSL_Types.Quaternion(); + } + + public void llSetPrimURL() + { + m_host.AddScriptLPS(1); + NotImplemented("llSetPrimURL"); + } + + public void llRefreshPrimURL() + { + m_host.AddScriptLPS(1); + NotImplemented("llRefreshPrimURL"); + } + + public string llEscapeURL(string url) + { + m_host.AddScriptLPS(1); + try + { + return Uri.EscapeUriString(url); + } + catch (Exception ex) + { + return "llEscapeURL: " + ex.ToString(); + } + } + + public string llUnescapeURL(string url) + { + m_host.AddScriptLPS(1); + try + { + return Uri.UnescapeDataString(url); + } + catch (Exception ex) + { + return "llUnescapeURL: " + ex.ToString(); + } + } + + public void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at) + { + m_host.AddScriptLPS(1); + NotImplemented("llMapDestination"); + } + + public void llAddToLandBanList(string avatar, double hours) + { + m_host.AddScriptLPS(1); + NotImplemented("llAddToLandBanList"); + } + + public void llRemoveFromLandPassList(string avatar) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveFromLandPassList"); + } + + public void llRemoveFromLandBanList(string avatar) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveFromLandBanList"); + } + + public void llSetCameraParams(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraParams"); + } + + public void llClearCameraParams() + { + m_host.AddScriptLPS(1); + NotImplemented("llClearCameraParams"); + } + + public double llListStatistics(int operation, LSL_Types.list src) + { + m_host.AddScriptLPS(1); + LSL_Types.list nums = LSL_Types.list.ToDoubleList(src); + switch (operation) + { + case LSL_BaseClass.LIST_STAT_RANGE: + return nums.Range(); + case LSL_BaseClass.LIST_STAT_MIN: + return nums.Min(); + case LSL_BaseClass.LIST_STAT_MAX: + return nums.Max(); + case LSL_BaseClass.LIST_STAT_MEAN: + return nums.Mean(); + case LSL_BaseClass.LIST_STAT_MEDIAN: + return nums.Median(); + case LSL_BaseClass.LIST_STAT_NUM_COUNT: + return nums.NumericLength(); + case LSL_BaseClass.LIST_STAT_STD_DEV: + return nums.StdDev(); + case LSL_BaseClass.LIST_STAT_SUM: + return nums.Sum(); + case LSL_BaseClass.LIST_STAT_SUM_SQUARES: + return nums.SumSqrs(); + case LSL_BaseClass.LIST_STAT_GEOMETRIC_MEAN: + return nums.GeometricMean(); + case LSL_BaseClass.LIST_STAT_HARMONIC_MEAN: + return nums.HarmonicMean(); + default: + return 0.0; + } + } + + public int llGetUnixTime() + { + m_host.AddScriptLPS(1); + return Util.UnixTimeSinceEpoch(); + } + + public int llGetParcelFlags(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + return (int)World.LandManager.getLandObject((float)pos.x, (float)pos.y).landData.landFlags; + } + + public int llGetRegionFlags() + { + m_host.AddScriptLPS(1); + return (int)World.RegionInfo.EstateSettings.regionFlags; + } + + public 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++) + { + ret += src1[i] ^ src2[c]; + + c++; + if (c > src2.Length) + c = 0; + } + return llStringToBase64(ret); + } + + public string llHTTPRequest(string url, LSL_Types.list parameters, string body) + { + m_host.AddScriptLPS(1); + IHttpRequests httpScriptMod = + m_ScriptEngine.World.RequestModuleInterface(); + List param = new List(); + foreach (object o in parameters.Data) + { + param.Add(o.ToString()); + } + LLUUID reqID = httpScriptMod. + StartHttpRequest(m_localID, m_itemID, url, param, body); + + if (!reqID.Equals(null)) + return reqID.ToString(); + else + return null; + } + + public void llResetLandBanList() + { + m_host.AddScriptLPS(1); + NotImplemented("llResetLandBanList"); + } + + public void llResetLandPassList() + { + m_host.AddScriptLPS(1); + NotImplemented("llResetLandPassList"); + } + + public int llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetParcelPrimCount"); + return 0; + } + + public LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetParcelPrimOwners"); + return new LSL_Types.list(); + } + + public int llGetObjectPrimCount(string object_id) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = World.GetSceneObjectPart(new LLUUID(object_id)); + if (part == null) + { + return 0; + } + else + { + return part.ParentGroup.Children.Count; + } + } + + public int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide) + { + m_host.AddScriptLPS(1); + // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation + // Which probably will be irrelevent in OpenSim.... + LandData land = World.GetLandData((float)pos.x, (float)pos.y); + float bonusfactor = World.RegionInfo.EstateSettings.objectBonusFactor; + if (land == null) + { + return 0; + } + if (sim_wide == 1) + { + decimal v = land.simwideArea * (decimal)(0.22) * (decimal)bonusfactor; + return (int)v; + } + else + { + decimal v = land.area * (decimal)(0.22) * (decimal)bonusfactor; + return (int)v; + } + + } + + public LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param) + { + m_host.AddScriptLPS(1); + LandData land = World.GetLandData((float)pos.x, (float)pos.y); + if (land == null) + { + return new LSL_Types.list(0); + } + LSL_Types.list ret = new LSL_Types.list(); + foreach (object o in param.Data) + { + switch (o.ToString()) + { + case "0": + ret = ret + new LSL_Types.list(land.landName); + break; + case "1": + ret = ret + new LSL_Types.list(land.landDesc); + break; + case "2": + ret = ret + new LSL_Types.list(land.ownerID.ToString()); + break; + case "3": + ret = ret + new LSL_Types.list(land.groupID.ToString()); + break; + case "4": + ret = ret + new LSL_Types.list(land.area); + break; + default: + ret = ret + new LSL_Types.list(0); + break; + } + } + return ret; + } + + public string llStringTrim(string src, int type) + { + m_host.AddScriptLPS(1); + if (type == (int)LSL_BaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); } + if (type == (int)LSL_BaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); } + if (type == (int)LSL_BaseClass.STRING_TRIM) { return src.Trim(); } + return src; + } + + // + // OpenSim functions + // + public int osTerrainSetHeight(int x, int y, double val) + { + m_host.AddScriptLPS(1); + if (x > 255 || x < 0 || y > 255 || y < 0) + LSLError("osTerrainSetHeight: Coordinate out of bounds"); + + if (World.PermissionsMngr.CanTerraform(m_host.OwnerID, new LLVector3(x, y, 0))) + { + World.Terrain.Set(x, y, val); + return 1; + } + else + { + return 0; + } + } + + public double osTerrainGetHeight(int x, int y) + { + m_host.AddScriptLPS(1); + if (x > 255 || x < 0 || y > 255 || y < 0) + LSLError("osTerrainGetHeight: Coordinate out of bounds"); + + return World.Terrain.GetHeight(x, y); + } + + public int osRegionRestart(double seconds) + { + m_host.AddScriptLPS(1); + if (World.PermissionsMngr.CanRestartSim(m_host.OwnerID)) + { + World.Restart((float)seconds); + return 1; + } + else + { + return 0; + } + } + + public void osRegionNotice(string msg) + { + m_host.AddScriptLPS(1); + World.SendGeneralAlert(msg); + } + + public void osSetRot(LLUUID target, Quaternion rotation) + { + m_host.AddScriptLPS(1); + if (World.Entities.ContainsKey(target)) + { + World.Entities[target].Rotation = rotation; + } + else + { + LSLError("osSetRot: Invalid target"); + } + } + + public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, + int timer) + { + m_host.AddScriptLPS(1); + if (dynamicID == String.Empty) + { + IDynamicTextureManager textureManager = World.RequestModuleInterface(); + LLUUID createdTexture = + textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, + extraParams, timer); + return createdTexture.ToString(); + } + else + { + //TODO update existing dynamic textures + } + + return LLUUID.Zero.ToString(); + } + + public bool osConsoleCommand(string command) + { + m_host.AddScriptLPS(1); + Nini.Config.IConfigSource config = new Nini.Config.IniConfigSource(Application.iniFilePath); + if (config.Configs["LL-Functions"] == null) + config.AddConfig("LL-Functions"); + + if (config.Configs["LL-Functions"].GetBoolean("AllowosConsoleCommand", false)) + { + if (World.PermissionsMngr.CanRunConsoleCommand(m_host.OwnerID)) + { + OpenSim.Framework.Console.MainConsole.Instance.RunCommand(command); + return true; + } + return false; + } + return false; + } + + private void NotImplemented(string command) + { + m_host.AddScriptLPS(1); + if (throwErrorOnNotImplemented) + throw new NotImplementedException("Command not implemented: " + command); + } + + private void LSLError(string msg) + { + m_host.AddScriptLPS(1); + throw new Exception("LSL Runtime Error: " + msg); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs index 56c4968e2b..42197a22c2 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs @@ -1,640 +1,646 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -using System.Collections.Generic; - -namespace OpenSim.Region.ScriptEngine.Common -{ - public interface LSL_BuiltIn_Commands_Interface - { - - // Interface used for loading and executing scripts - - string State(); - - double llSin(double f); - double llCos(double f); - double llTan(double f); - double llAtan2(double x, double y); - double llSqrt(double f); - double llPow(double fbase, double fexponent); - int llAbs(int i); - double llFabs(double f); - double llFrand(double mag); - int llFloor(double f); - int llCeil(double f); - int llRound(double f); - double llVecMag(LSL_Types.Vector3 v); - LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v); - double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b); - LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r); - LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v); - LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up); - LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r); - LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r); - LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r); - LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end); - void llWhisper(int channelID, string text); - //void llSay(int channelID, string text); - void llSay(int channelID, string text); - void llShout(int channelID, string text); - int llListen(int channelID, string name, string ID, string msg); - void llListenControl(int number, int active); - void llListenRemove(int number); - void llSensor(string name, string id, int type, double range, double arc); - void llSensorRepeat(string name, string id, int type, double range, double arc, double rate); - void llSensorRemove(); - string llDetectedName(int number); - string llDetectedKey(int number); - string llDetectedOwner(int number); - int llDetectedType(int number); - LSL_Types.Vector3 llDetectedPos(int number); - LSL_Types.Vector3 llDetectedVel(int number); - LSL_Types.Vector3 llDetectedGrab(int number); - LSL_Types.Quaternion llDetectedRot(int number); - int llDetectedGroup(int number); - int llDetectedLinkNumber(int number); - void llDie(); - double llGround(LSL_Types.Vector3 offset); - double llCloud(LSL_Types.Vector3 offset); - LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset); - void llSetStatus(int status, int value); - int llGetStatus(int status); - void llSetScale(LSL_Types.Vector3 scale); - LSL_Types.Vector3 llGetScale(); - void llSetColor(LSL_Types.Vector3 color, int face); - double llGetAlpha(int face); - void llSetAlpha(double alpha, int face); - LSL_Types.Vector3 llGetColor(int face); - void llSetTexture(string texture, int face); - void llScaleTexture(double u, double v, int face); - void llOffsetTexture(double u, double v, int face); - void llRotateTexture(double rotation, int face); - string llGetTexture(int face); - void llSetPos(LSL_Types.Vector3 pos); - - //wiki: vector llGetPos() - LSL_Types.Vector3 llGetPos(); - //wiki: vector llGetLocalPos() - LSL_Types.Vector3 llGetLocalPos(); - //wiki: llSetRot(rotation rot) - void llSetRot(LSL_Types.Quaternion rot); - //wiki: rotation llGetRot() - LSL_Types.Quaternion llGetRot(); - //wiki: rotation llGetLocalRot() - LSL_Types.Quaternion llGetLocalRot(); - //wiki: llSetForce(vector force, integer local) - void llSetForce(LSL_Types.Vector3 force, int local); - //wiki: vector llGetForce() - LSL_Types.Vector3 llGetForce(); - //wiki: integer llTarget(vector position, double range) - int llTarget(LSL_Types.Vector3 position, double range); - //wiki: llTargetRemove(integer number) - void llTargetRemove(int number); - //wiki: integer llRotTarget(rotation rot, double error) - int llRotTarget(LSL_Types.Quaternion rot, double error); - //wiki: integer llRotTargetRemove(integer number) - void llRotTargetRemove(int number); - //wiki: llMoveToTarget(vector target, double tau) - void llMoveToTarget(LSL_Types.Vector3 target, double tau); - //wiki: llStopMoveToTarget() - void llStopMoveToTarget(); - //wiki: llApplyImpulse(vector force, integer local) - void llApplyImpulse(LSL_Types.Vector3 force, int local); - //wiki: llapplyRotationalImpulse(vector force, integer local) - void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local); - //wiki: llSetTorque(vector torque, integer local) - void llSetTorque(LSL_Types.Vector3 torque, int local); - //wiki: vector llGetTorque() - LSL_Types.Vector3 llGetTorque(); - //wiki: llSeForceAndTorque(vector force, vector torque, integer local) - void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local); - //wiki: vector llGetVel() - LSL_Types.Vector3 llGetVel(); - //wiki: vector llGetAccel() - LSL_Types.Vector3 llGetAccel(); - //wiki: vector llGetOmega() - LSL_Types.Vector3 llGetOmega(); - //wiki: double llGetTimeOfDay() - double llGetTimeOfDay(); - //wiki: double llGetWallclock() - double llGetWallclock(); - //wiki: double llGetTime() - double llGetTime(); - //wiki: llResetTime() - void llResetTime(); - //wiki: double llGetAndResetTime() - double llGetAndResetTime(); - //wiki (deprecated) llSound(string sound, double volume, integer queue, integer loop) - void llSound(); - //wiki: llPlaySound(string sound, double volume) - void llPlaySound(string sound, double volume); - //wiki: llLoopSound(string sound, double volume) - void llLoopSound(string sound, double volume); - //wiki: llLoopSoundMaster(string sound, double volume) - void llLoopSoundMaster(string sound, double volume); - //wiki: llLoopSoundSlave(string sound, double volume) - void llLoopSoundSlave(string sound, double volume); - //wiki llPlaySoundSlave(string sound, double volume) - void llPlaySoundSlave(string sound, double volume); - //wiki: llTriggerSound(string sound, double volume) - void llTriggerSound(string sound, double volume); - //wiki: llStopSound() - void llStopSound(); - //wiki: llPreloadSound(string sound) - void llPreloadSound(string sound); - //wiki: string llGetSubString(string src, integer start, integer end) - string llGetSubString(string src, int start, int end); - //wiki: string llDeleteSubString(string src, integer start, integer end) - string llDeleteSubString(string src, int start, int end); - //wiki string llInsertString(string dst, integer position, string src) - string llInsertString(string dst, int position, string src); - //wiki: string llToUpper(string source) - string llToUpper(string source); - //wiki: string llToLower(string source) - string llToLower(string source); - //wiki: integer llGiveMoney(key destination, integer amount) - int llGiveMoney(string destination, int amount); - //wiki: (deprecated) - void llMakeExplosion(); - //wiki: (deprecated) - void llMakeFountain(); - //wiki: (deprecated) - void llMakeSmoke(); - //wiki: (deprecated) - void llMakeFire(); - //wiki: llRezObject(string inventory, vector pos, vector rel, rotation rot, integer param) - void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Quaternion rot, int param); - //wiki: llLookAt(vector target, double strength, double damping) - void llLookAt(LSL_Types.Vector3 target, double strength, double damping); - //wiki: llStopLookAt() - void llStopLookAt(); - //wiki: llSetTimerEvent(double sec) - void llSetTimerEvent(double sec); - //wiki: llSleep(double sec) - void llSleep(double sec); - //wiki: double llGetMass() - double llGetMass(); - //wiki: llCollisionFilter(string name, key id, integer accept) - void llCollisionFilter(string name, string id, int accept); - //wiki: llTakeControls(integer controls, integer accept, integer pass_on) - void llTakeControls(int controls, int accept, int pass_on); - //wiki: llReleaseControls() - void llReleaseControls(); - //wiki: llAttachToAvatar(integer attachment) - void llAttachToAvatar(int attachment); - //wiki: llDetachFromAvatar() - void llDetachFromAvatar(); - //wiki: (deprecated) llTakeCamera() - void llTakeCamera(); - //wiki: (deprecated) llReleaseCamera() - void llReleaseCamera(); - //wiki: key llGetOwner() - string llGetOwner(); - //wiki: llInstantMessage(key user, string message) - void llInstantMessage(string user, string message); - //wiki: llEmail(string address, string subject, string message) - void llEmail(string address, string subject, string message); - //wiki: llGetNextEmail(string address, string subject) - void llGetNextEmail(string address, string subject); - //wiki: key llGetKey() - string llGetKey(); - //wiki: llSetBuoyancy(double buoyancy) - void llSetBuoyancy(double buoyancy); - //wiki: llSetHoverHeight(double height, integer water, double tau) - void llSetHoverHeight(double height, int water, double tau); - //wiki: llStopHover - void llStopHover(); - //wiki: llMinEventDelay(double delay) - void llMinEventDelay(double delay); - //wiki: (deprecated) llSoundPreload() - void llSoundPreload(); - //wiki: llRotLookAt(rotation target, double strength, double damping) - void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping); - //wiki: integer llStringLength(string str) - int llStringLength(string str); - //wiki: llStartAnimation(string anim) - void llStartAnimation(string anim); - //wiki: llStopAnimation(string anim) - void llStopAnimation(string anim); - //wiki: (deprecated) llPointAt - void llPointAt(); - //wiki: (deprecated) llStopPointAt - void llStopPointAt(); - //wiki: llTargetOmega(vector axis, double spinrate, double gain) - void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain); - //wiki: integer llGetStartParameter() - int llGetStartParameter(); - //wiki: llGodLikeRezObject(key inventory, vector pos) - void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos); - //wiki: llRequestPermissions(key agent, integer perm) - void llRequestPermissions(string agent, int perm); - //wiki: key llGetPermissionsKey() - string llGetPermissionsKey(); - //wiki: integer llGetPermissions() - int llGetPermissions(); - //wiki integer llGetLinkNumber() - int llGetLinkNumber(); - //wiki: llSetLinkColor(integer linknumber, vector color, integer face) - void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face); - //wiki: llCreateLink(key target, integer parent) - void llCreateLink(string target, int parent); - //wiki: llBreakLink(integer linknum) - void llBreakLink(int linknum); - //wiki: llBreakAllLinks() - void llBreakAllLinks(); - //wiki: key llGetLinkKey(integer linknum) - string llGetLinkKey(int linknum); - //wiki: llGetLinkName(integer linknum) - string llGetLinkName(int linknum); - //wiki: integer llGetInventoryNumber(integer type) - int llGetInventoryNumber(int type); - //wiki: string llGetInventoryName(integer type, integer number) - string llGetInventoryName(int type, int number); - //wiki: llSetScriptState(string name, integer run) - void llSetScriptState(string name, int run); - //wiki: double llGetEnergy() - double llGetEnergy(); - //wiki: llGiveInventory(key destination, string inventory) - void llGiveInventory(string destination, string inventory); - //wiki: llRemoveInventory(string item) - void llRemoveInventory(string item); - //wiki: llSetText(string text, vector color, double alpha) - void llSetText(string text, LSL_Types.Vector3 color, double alpha); - //wiki: double llWater(vector offset) - double llWater(LSL_Types.Vector3 offset); - //wiki: llPassTouches(integer pass) - void llPassTouches(int pass); - //wiki: key llRequestAgentData(key id, integer data) - string llRequestAgentData(string id, int data); - //wiki: key llRequestInventoryData(string name) - string llRequestInventoryData(string name); - //wiki: llSetDamage(double damage) - void llSetDamage(double damage); - //wiki: llTeleportAgentHome(key agent) - void llTeleportAgentHome(string agent); - //wiki: llModifyLand(integer action, integer brush) - void llModifyLand(int action, int brush); - //wiki: llCollisionSound(string impact_sound, double impact_volume) - void llCollisionSound(string impact_sound, double impact_volume); - //wiki: llCollisionSprite(string impact_sprite) - void llCollisionSprite(string impact_sprite); - //wiki: string llGetAnimation(key id) - string llGetAnimation(string id); - //wiki: llResetScript() - void llResetScript(); - //wiki: llMessageLinked(integer linknum, integer num, string str, key id) - void llMessageLinked(int linknum, int num, string str, string id); - //wiki: llPushObject(key target, vector impulse, vector ang_impulse, integer local) - void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local); - //wiki: llPassCollisions(integer pass) - void llPassCollisions(int pass); - //wiki: string llGetScriptName() - string llGetScriptName(); - //wiki: integer llGetNumberOfSides() - int llGetNumberOfSides(); - //wiki: rotation llAxisAngle2Rot(vector axis, double angle) - LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle); - //wiki: vector llRot2Axis(rotation rot) - LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot); - void llRot2Angle(); - //wiki: double llAcos(double val) - double llAcos(double val); - //wiki: double llAsin(double val) - double llAsin(double val); - //wiki: double llAngleBetween(rotation a, rotation b) - double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b); - //wiki: string llGetInventoryKey(string name) - string llGetInventoryKey(string name); - //wiki: llAllowInventoryDrop(integer add) - void llAllowInventoryDrop(int add); - //wiki: vector llGetSunDirection() - LSL_Types.Vector3 llGetSunDirection(); - //wiki: vector llGetTextureOffset(integer face) - LSL_Types.Vector3 llGetTextureOffset(int face); - //wiki: vector llGetTextureScale(integer side) - LSL_Types.Vector3 llGetTextureScale(int side); - //wiki: double llGetTextureRot(integer side) - double llGetTextureRot(int side); - //wiki: integer llSubStringIndex(string source, string pattern) - int llSubStringIndex(string source, string pattern); - //wiki: key llGetOwnerKey(key id) - string llGetOwnerKey(string id); - //wiki: vector llGetCenterOfMass() - LSL_Types.Vector3 llGetCenterOfMass(); - //wiki: list llListSort(list src, integer stride, integer ascending) - LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending); - //integer llGetListLength(list src) - int llGetListLength(LSL_Types.list src); - //wiki: integer llList2Integer(list src, integer index) - int llList2Integer(LSL_Types.list src, int index); - //wiki: double llList2double(list src, integer index) - double osList2Double(LSL_Types.list src, int index); - //wiki: string llList2String(list src, integer index) - string llList2String(LSL_Types.list src, int index); - //wiki: key llList2Key(list src, integer index) - string llList2Key(LSL_Types.list src, int index); - //wiki: vector llList2Vector(list src, integer index) - LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index); - //wiki rotation llList2Rot(list src, integer index) - LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index); - //wiki: list llList2List(list src, integer start, integer end) - LSL_Types.list llList2List(LSL_Types.list src, int start, int end); - //wiki: llDeleteSubList(list src, integer start, integer end) - LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end); - //wiki: integer llGetListEntryType( list src, integer index ) - int llGetListEntryType(LSL_Types.list src, int index); - //wiki: string llList2CSV( list src ) - string llList2CSV(LSL_Types.list src); - //wiki: list llCSV2List( string src ) - LSL_Types.list llCSV2List(string src); - //wiki: list llListRandomize( list src, integer stride ) - LSL_Types.list llListRandomize(LSL_Types.list src, int stride); - //wiki: list llList2ListStrided( list src, integer start, integer end, integer stride ) - LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride); - //wiki: vector llGetRegionCorner( ) - LSL_Types.Vector3 llGetRegionCorner(); - //wiki: list llListInsertList( list dest, list src, integer start ) - LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start); - //wiki: integer llListFindList( list src, list test ) - int llListFindList(LSL_Types.list src, LSL_Types.list test); - //wiki: string llGetObjectName() - string llGetObjectName(); - //wiki: llSetObjectName(string name) - void llSetObjectName(string name); - //wiki: string llGetDate() - string llGetDate(); - //wiki: integer llEdgeOfWorld(vector pos, vector dir) - int llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir); - //wiki: integer llGetAgentInfo(key id) - int llGetAgentInfo(string id); - //wiki: llAdjustSoundVolume(double volume) - void llAdjustSoundVolume(double volume); - //wiki: llSetSoundQueueing(integer queue) - void llSetSoundQueueing(int queue); - //wiki: llSetSoundRadius(double radius) - void llSetSoundRadius(double radius); - //wiki: string llKey2Name(key id) - string llKey2Name(string id); - //wiki: llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, double start, double length, double rate) - void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate); - //wiki: llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) - void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, - LSL_Types.Vector3 bottom_south_west); - - //wiki: llEjectFromLand(key pest) - void llEjectFromLand(string pest); - void llParseString2List(); - //wiki: integer llOverMyLand(key id) - int llOverMyLand(string id); - //wiki: key llGetLandOwnerAt(vector pos) - string llGetLandOwnerAt(LSL_Types.Vector3 pos); - //wiki: key llGetNotecardLine(string name, integer line) - string llGetNotecardLine(string name, int line); - //wiki: vector llGetAgentSize(key id) - LSL_Types.Vector3 llGetAgentSize(string id); - //wiki: integer llSameGroup(key agent) - int llSameGroup(string agent); - //wiki: llUnSit(key id) - void llUnSit(string id); - //wiki: vector llGroundSlope(vector offset) - LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset); - //wiki: vector llGroundNormal(vector offset) - LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset); - //wiki: vector llGroundContour(vector offset) - LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset); - //wiki: integer llGetAttached() - int llGetAttached(); - //wiki: integer llGetFreeMemory() - int llGetFreeMemory(); - //wiki: string llGetRegionName() - string llGetRegionName(); - //wiki: double llGetRegionTimeDilation() - double llGetRegionTimeDilation(); - //wiki: double llGetRegionFPS() - double llGetRegionFPS(); - //wiki: llParticleSystem(List rules - void llParticleSystem(List rules); - //wiki: llGroundRepel(double height, integer water, double tau) - void llGroundRepel(double height, int water, double tau); - void llGiveInventoryList(); - //wiki: llSetVehicleType(integer type) - void llSetVehicleType(int type); - //wiki: llSetVehicledoubleParam(integer param, double value) - void llSetVehicledoubleParam(int param, double value); - //wiki: llSetVehicleVectorParam(integer param, vector vec) - void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec); - //wiki: llSetVehicleRotationParam(integer param, rotation rot) - void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot); - //wiki: llSetVehicleFlags(integer flags) - void llSetVehicleFlags(int flags); - //wiki: llRemoveVehicleFlags(integer flags) - void llRemoveVehicleFlags(int flags); - //wiki: llSitTarget(vector offset, rotation rot) - void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot); - //wiki key llAvatarOnSitTarget() - string llAvatarOnSitTarget(); - //wiki: llAddToLandPassList(key avatar, double hours) - void llAddToLandPassList(string avatar, double hours); - //wiki: llSetTouchText(string text) - void llSetTouchText(string text); - //wiki: llSetSitText(string text) - void llSetSitText(string text); - //wiki: llSetCameraEyeOffset(vector offset) - void llSetCameraEyeOffset(LSL_Types.Vector3 offset); - //wiki: llSeteCameraAtOffset(vector offset) - void llSetCameraAtOffset(LSL_Types.Vector3 offset); - // - string llDumpList2String(LSL_Types.list src, string seperator); - //wiki: integer llScriptDanger(vector pos) - void llScriptDanger(LSL_Types.Vector3 pos); - //wiki: llDialog( key avatar, string message, list buttons, integer chat_channel ) - void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel); - //wiki: llVolumeDetect(integer detect) - void llVolumeDetect(int detect); - //wiki: llResetOtherScript(string name) - void llResetOtherScript(string name); - //wiki: integer llGetScriptState(string name) - int llGetScriptState(string name); - //wiki: (deprecated) - void llRemoteLoadScript(); - //wiki: llSetRemoteScriptAccessPin(integer pin) - void llSetRemoteScriptAccessPin(int pin); - //wiki: llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param) - void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param); - //wiki: llOpenRemoteDataChannel() - void llOpenRemoteDataChannel(); - //wiki: key llSendRemoteData(key channel, string dest, integer idata, string sdata) - string llSendRemoteData(string channel, string dest, int idata, string sdata); - //wiki: llRemoteDataReply(key channel, key message_id, string sdata, integer idata) - void llRemoteDataReply(string channel, string message_id, string sdata, int idata); - //wiki: llCloseRemoteDataChannel(key channel) - void llCloseRemoteDataChannel(string channel); - //wiki: string llMD5String(string src, integer nonce) - string llMD5String(string src, int nonce); - //wiki: llSetPrimitiveParams( list rules ) - void llSetPrimitiveParams(LSL_Types.list rules); - //wiki: string llStringToBase64(string str) - string llStringToBase64(string str); - //wiki: string llBase64ToString(string str) - string llBase64ToString(string str); - //wiki: (deprecated) - void llXorBase64Strings(); - //wiki: llRemoteDataSetRegion() - void llRemoteDataSetRegion(); - //wiki: double llLog10(double val) - double llLog10(double val); - //wiki: double llLog(double val) - double llLog(double val); - //wiki: list llGetAnimationList( key id ) - LSL_Types.list llGetAnimationList(string id); - //wiki: llSetParcelMusicURL(string url) - void llSetParcelMusicURL(string url); - //wiki: vector llGetRootPosition() - LSL_Types.Vector3 llGetRootPosition(); - //wiki: rotation llGetRootRotation() - LSL_Types.Quaternion llGetRootRotation(); - //wiki: string llGetObjectDesc() - string llGetObjectDesc(); - //wiki: llSetObjectDesc(string desc) - void llSetObjectDesc(string desc); - //wiki: key llGetCreator() - string llGetCreator(); - //wiki: string llGetTimestamp() - string llGetTimestamp(); - //wiki: llSetLinkAlpha(integer linknumber, double alpha, integer face) - void llSetLinkAlpha(int linknumber, double alpha, int face); - //wiki: integer llGetNumberOfPrims() - int llGetNumberOfPrims(); - //wiki: key llGetNumberOfNotecardLines(string name) - string llGetNumberOfNotecardLines(string name); - //wiki: list llGetBoundingBox( key object ) - LSL_Types.list llGetBoundingBox(string obj); - //wiki: vector llGetGeometricCenter() - LSL_Types.Vector3 llGetGeometricCenter(); - void llGetPrimitiveParams(); - //wiki: string llIntegerToBase64(integer number) - string llIntegerToBase64(int number); - //wiki integer llBase64ToInteger(string str) - int llBase64ToInteger(string str); - //wiki: double llGetGMTclock() - double llGetGMTclock(); - //wiki: string llGetSimulatorHostname() - string llGetSimulatorHostname(); - //llSetLocalRot(rotation rot) - void llSetLocalRot(LSL_Types.Quaternion rot); - //wiki: list llParseStringKeepNulls( string src, list separators, list spacers ) - LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers); - //wiki: llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, integer param) - void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, - LSL_Types.Quaternion rot, int param); - - //wiki: integer llGetObjectPermMask(integer mask) - int llGetObjectPermMask(int mask); - //wiki: llSetObjectPermMask(integer mask, integer value) - void llSetObjectPermMask(int mask, int value); - //wiki integer llGetInventoryPermMask(string item, integer mask) - void llGetInventoryPermMask(string item, int mask); - //wiki: llSetInventoryPermMask(string item, integer mask, integer value) - void llSetInventoryPermMask(string item, int mask, int value); - //wiki: key llGetInventoryCreator(string item) - string llGetInventoryCreator(string item); - //wiki: llOwnerSay(string msg) - void llOwnerSay(string msg); - //wiki: key llRequestSimulatorData(string simulator, integer data) - void llRequestSimulatorData(string simulator, int data); - //wiki: llForceMouselook(integer mouselook) - void llForceMouselook(int mouselook); - //wiki: double llGetObjectMass(key id) - double llGetObjectMass(string id); - LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end); - //wiki: llLoadURL(key avatar_id, string message, string url) - void llLoadURL(string avatar_id, string message, string url); - //wiki: llParcelMediaCommandList( list commandList ) - void llParcelMediaCommandList(LSL_Types.list commandList); - void llParcelMediaQuery(); - //wiki integer llModPow(integer a, integer b, integer c) - int llModPow(int a, int b, int c); - //wiki: integer llGetInventoryType(string name) - int llGetInventoryType(string name); - //wiki: llSetPayPrice( integer price, list quick_pay_buttons ) - void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons); - //wiki: vector llGetCameraPos() - LSL_Types.Vector3 llGetCameraPos(); - //wiki rotation llGetCameraRot() - LSL_Types.Quaternion llGetCameraRot(); - //wiki: (deprecated) - void llSetPrimURL(); - //wiki: (deprecated) - void llRefreshPrimURL(); - //wiki: string llEscapeURL(string url) - string llEscapeURL(string url); - //wiki: string llUnescapeURL(string url) - string llUnescapeURL(string url); - //wiki: llMapDestination(string simname, vector pos, vector look_at) - void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at); - //wiki: llAddToLandBanList(key avatar, double hours) - void llAddToLandBanList(string avatar, double hours); - //wiki: llRemoveFromLandPassList(key avatar) - void llRemoveFromLandPassList(string avatar); - //wiki: llRemoveFromLandBanList(key avatar) - void llRemoveFromLandBanList(string avatar); - //wiki: llSetCameraParams( list rules ) - void llSetCameraParams(LSL_Types.list rules); - //wiki: llClearCameraParams() - void llClearCameraParams(); - //wiki: double llListStatistics( integer operation, list src ) - double llListStatistics(int operation, LSL_Types.list src); - //wiki: integer llGetUnixTime() - int llGetUnixTime(); - //wiki: integer llGetParcelFlags(vector pos) - int llGetParcelFlags(LSL_Types.Vector3 pos); - //wiki: integer llGetRegionFlags() - int llGetRegionFlags(); - //wiki: string llXorBase64StringsCorrect(string str1, string str2) - string llXorBase64StringsCorrect(string str1, string str2); - string llHTTPRequest(string url, LSL_Types.list parameters, string body); - //wiki: llResetLandBanList() - void llResetLandBanList(); - //wiki: llResetLandPassList() - void llResetLandPassList(); - //wiki integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide) - int llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide); - //wiki: list llGetParcelPrimOwners( vector pos ) - LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos); - //wiki: integer llGetObjectPrimCount(key object_id) - int llGetObjectPrimCount(string object_id); - //wiki: integer llGetParcelMaxPrims( vector pos, integer sim_wide ) - int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide); - //wiki list llGetParcelDetails(vector pos, list params) - LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param); - - //OpenSim functions - string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer); - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System.Collections.Generic; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public interface LSL_BuiltIn_Commands_Interface + { + + // Interface used for loading and executing scripts + + string State { get; set; } + + double llSin(double f); + double llCos(double f); + double llTan(double f); + double llAtan2(double x, double y); + double llSqrt(double f); + double llPow(double fbase, double fexponent); + int llAbs(int i); + double llFabs(double f); + double llFrand(double mag); + int llFloor(double f); + int llCeil(double f); + int llRound(double f); + double llVecMag(LSL_Types.Vector3 v); + LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v); + double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b); + LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r); + LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v); + LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up); + LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r); + LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r); + LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r); + LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end); + void llWhisper(int channelID, string text); + //void llSay(int channelID, string text); + void llSay(int channelID, string text); + void llShout(int channelID, string text); + int llListen(int channelID, string name, string ID, string msg); + void llListenControl(int number, int active); + void llListenRemove(int number); + void llSensor(string name, string id, int type, double range, double arc); + void llSensorRepeat(string name, string id, int type, double range, double arc, double rate); + void llSensorRemove(); + string llDetectedName(int number); + string llDetectedKey(int number); + string llDetectedOwner(int number); + int llDetectedType(int number); + LSL_Types.Vector3 llDetectedPos(int number); + LSL_Types.Vector3 llDetectedVel(int number); + LSL_Types.Vector3 llDetectedGrab(int number); + LSL_Types.Quaternion llDetectedRot(int number); + int llDetectedGroup(int number); + int llDetectedLinkNumber(int number); + void llDie(); + double llGround(LSL_Types.Vector3 offset); + double llCloud(LSL_Types.Vector3 offset); + LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset); + void llSetStatus(int status, int value); + int llGetStatus(int status); + void llSetScale(LSL_Types.Vector3 scale); + LSL_Types.Vector3 llGetScale(); + void llSetColor(LSL_Types.Vector3 color, int face); + double llGetAlpha(int face); + void llSetAlpha(double alpha, int face); + LSL_Types.Vector3 llGetColor(int face); + void llSetTexture(string texture, int face); + void llScaleTexture(double u, double v, int face); + void llOffsetTexture(double u, double v, int face); + void llRotateTexture(double rotation, int face); + string llGetTexture(int face); + void llSetPos(LSL_Types.Vector3 pos); + + //wiki: vector llGetPos() + LSL_Types.Vector3 llGetPos(); + //wiki: vector llGetLocalPos() + LSL_Types.Vector3 llGetLocalPos(); + //wiki: llSetRot(rotation rot) + void llSetRot(LSL_Types.Quaternion rot); + //wiki: rotation llGetRot() + LSL_Types.Quaternion llGetRot(); + //wiki: rotation llGetLocalRot() + LSL_Types.Quaternion llGetLocalRot(); + //wiki: llSetForce(vector force, integer local) + void llSetForce(LSL_Types.Vector3 force, int local); + //wiki: vector llGetForce() + LSL_Types.Vector3 llGetForce(); + //wiki: integer llTarget(vector position, double range) + int llTarget(LSL_Types.Vector3 position, double range); + //wiki: llTargetRemove(integer number) + void llTargetRemove(int number); + //wiki: integer llRotTarget(rotation rot, double error) + int llRotTarget(LSL_Types.Quaternion rot, double error); + //wiki: integer llRotTargetRemove(integer number) + void llRotTargetRemove(int number); + //wiki: llMoveToTarget(vector target, double tau) + void llMoveToTarget(LSL_Types.Vector3 target, double tau); + //wiki: llStopMoveToTarget() + void llStopMoveToTarget(); + //wiki: llApplyImpulse(vector force, integer local) + void llApplyImpulse(LSL_Types.Vector3 force, int local); + //wiki: llapplyRotationalImpulse(vector force, integer local) + void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local); + //wiki: llSetTorque(vector torque, integer local) + void llSetTorque(LSL_Types.Vector3 torque, int local); + //wiki: vector llGetTorque() + LSL_Types.Vector3 llGetTorque(); + //wiki: llSeForceAndTorque(vector force, vector torque, integer local) + void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local); + //wiki: vector llGetVel() + LSL_Types.Vector3 llGetVel(); + //wiki: vector llGetAccel() + LSL_Types.Vector3 llGetAccel(); + //wiki: vector llGetOmega() + LSL_Types.Vector3 llGetOmega(); + //wiki: double llGetTimeOfDay() + double llGetTimeOfDay(); + //wiki: double llGetWallclock() + double llGetWallclock(); + //wiki: double llGetTime() + double llGetTime(); + //wiki: llResetTime() + void llResetTime(); + //wiki: double llGetAndResetTime() + double llGetAndResetTime(); + //wiki (deprecated) llSound(string sound, double volume, integer queue, integer loop) + void llSound(); + //wiki: llPlaySound(string sound, double volume) + void llPlaySound(string sound, double volume); + //wiki: llLoopSound(string sound, double volume) + void llLoopSound(string sound, double volume); + //wiki: llLoopSoundMaster(string sound, double volume) + void llLoopSoundMaster(string sound, double volume); + //wiki: llLoopSoundSlave(string sound, double volume) + void llLoopSoundSlave(string sound, double volume); + //wiki llPlaySoundSlave(string sound, double volume) + void llPlaySoundSlave(string sound, double volume); + //wiki: llTriggerSound(string sound, double volume) + void llTriggerSound(string sound, double volume); + //wiki: llStopSound() + void llStopSound(); + //wiki: llPreloadSound(string sound) + void llPreloadSound(string sound); + //wiki: string llGetSubString(string src, integer start, integer end) + string llGetSubString(string src, int start, int end); + //wiki: string llDeleteSubString(string src, integer start, integer end) + string llDeleteSubString(string src, int start, int end); + //wiki string llInsertString(string dst, integer position, string src) + string llInsertString(string dst, int position, string src); + //wiki: string llToUpper(string source) + string llToUpper(string source); + //wiki: string llToLower(string source) + string llToLower(string source); + //wiki: integer llGiveMoney(key destination, integer amount) + int llGiveMoney(string destination, int amount); + //wiki: (deprecated) + void llMakeExplosion(); + //wiki: (deprecated) + void llMakeFountain(); + //wiki: (deprecated) + void llMakeSmoke(); + //wiki: (deprecated) + void llMakeFire(); + //wiki: llRezObject(string inventory, vector pos, vector rel, rotation rot, integer param) + void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Quaternion rot, int param); + //wiki: llLookAt(vector target, double strength, double damping) + void llLookAt(LSL_Types.Vector3 target, double strength, double damping); + //wiki: llStopLookAt() + void llStopLookAt(); + //wiki: llSetTimerEvent(double sec) + void llSetTimerEvent(double sec); + //wiki: llSleep(double sec) + void llSleep(double sec); + //wiki: double llGetMass() + double llGetMass(); + //wiki: llCollisionFilter(string name, key id, integer accept) + void llCollisionFilter(string name, string id, int accept); + //wiki: llTakeControls(integer controls, integer accept, integer pass_on) + void llTakeControls(int controls, int accept, int pass_on); + //wiki: llReleaseControls() + void llReleaseControls(); + //wiki: llAttachToAvatar(integer attachment) + void llAttachToAvatar(int attachment); + //wiki: llDetachFromAvatar() + void llDetachFromAvatar(); + //wiki: (deprecated) llTakeCamera() + void llTakeCamera(); + //wiki: (deprecated) llReleaseCamera() + void llReleaseCamera(); + //wiki: key llGetOwner() + string llGetOwner(); + //wiki: llInstantMessage(key user, string message) + void llInstantMessage(string user, string message); + //wiki: llEmail(string address, string subject, string message) + void llEmail(string address, string subject, string message); + //wiki: llGetNextEmail(string address, string subject) + void llGetNextEmail(string address, string subject); + //wiki: key llGetKey() + string llGetKey(); + //wiki: llSetBuoyancy(double buoyancy) + void llSetBuoyancy(double buoyancy); + //wiki: llSetHoverHeight(double height, integer water, double tau) + void llSetHoverHeight(double height, int water, double tau); + //wiki: llStopHover + void llStopHover(); + //wiki: llMinEventDelay(double delay) + void llMinEventDelay(double delay); + //wiki: (deprecated) llSoundPreload() + void llSoundPreload(); + //wiki: llRotLookAt(rotation target, double strength, double damping) + void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping); + //wiki: integer llStringLength(string str) + int llStringLength(string str); + //wiki: llStartAnimation(string anim) + void llStartAnimation(string anim); + //wiki: llStopAnimation(string anim) + void llStopAnimation(string anim); + //wiki: (deprecated) llPointAt + void llPointAt(); + //wiki: (deprecated) llStopPointAt + void llStopPointAt(); + //wiki: llTargetOmega(vector axis, double spinrate, double gain) + void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain); + //wiki: integer llGetStartParameter() + int llGetStartParameter(); + //wiki: llGodLikeRezObject(key inventory, vector pos) + void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos); + //wiki: llRequestPermissions(key agent, integer perm) + void llRequestPermissions(string agent, int perm); + //wiki: key llGetPermissionsKey() + string llGetPermissionsKey(); + //wiki: integer llGetPermissions() + int llGetPermissions(); + //wiki integer llGetLinkNumber() + int llGetLinkNumber(); + //wiki: llSetLinkColor(integer linknumber, vector color, integer face) + void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face); + //wiki: llCreateLink(key target, integer parent) + void llCreateLink(string target, int parent); + //wiki: llBreakLink(integer linknum) + void llBreakLink(int linknum); + //wiki: llBreakAllLinks() + void llBreakAllLinks(); + //wiki: key llGetLinkKey(integer linknum) + string llGetLinkKey(int linknum); + //wiki: llGetLinkName(integer linknum) + string llGetLinkName(int linknum); + //wiki: integer llGetInventoryNumber(integer type) + int llGetInventoryNumber(int type); + //wiki: string llGetInventoryName(integer type, integer number) + string llGetInventoryName(int type, int number); + //wiki: llSetScriptState(string name, integer run) + void llSetScriptState(string name, int run); + //wiki: double llGetEnergy() + double llGetEnergy(); + //wiki: llGiveInventory(key destination, string inventory) + void llGiveInventory(string destination, string inventory); + //wiki: llRemoveInventory(string item) + void llRemoveInventory(string item); + //wiki: llSetText(string text, vector color, double alpha) + void llSetText(string text, LSL_Types.Vector3 color, double alpha); + //wiki: double llWater(vector offset) + double llWater(LSL_Types.Vector3 offset); + //wiki: llPassTouches(integer pass) + void llPassTouches(int pass); + //wiki: key llRequestAgentData(key id, integer data) + string llRequestAgentData(string id, int data); + //wiki: key llRequestInventoryData(string name) + string llRequestInventoryData(string name); + //wiki: llSetDamage(double damage) + void llSetDamage(double damage); + //wiki: llTeleportAgentHome(key agent) + void llTeleportAgentHome(string agent); + //wiki: llModifyLand(integer action, integer brush) + void llModifyLand(int action, int brush); + //wiki: llCollisionSound(string impact_sound, double impact_volume) + void llCollisionSound(string impact_sound, double impact_volume); + //wiki: llCollisionSprite(string impact_sprite) + void llCollisionSprite(string impact_sprite); + //wiki: string llGetAnimation(key id) + string llGetAnimation(string id); + //wiki: llResetScript() + void llResetScript(); + //wiki: llMessageLinked(integer linknum, integer num, string str, key id) + void llMessageLinked(int linknum, int num, string str, string id); + //wiki: llPushObject(key target, vector impulse, vector ang_impulse, integer local) + void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local); + //wiki: llPassCollisions(integer pass) + void llPassCollisions(int pass); + //wiki: string llGetScriptName() + string llGetScriptName(); + //wiki: integer llGetNumberOfSides() + int llGetNumberOfSides(); + //wiki: rotation llAxisAngle2Rot(vector axis, double angle) + LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle); + //wiki: vector llRot2Axis(rotation rot) + LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot); + void llRot2Angle(); + //wiki: double llAcos(double val) + double llAcos(double val); + //wiki: double llAsin(double val) + double llAsin(double val); + //wiki: double llAngleBetween(rotation a, rotation b) + double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b); + //wiki: string llGetInventoryKey(string name) + string llGetInventoryKey(string name); + //wiki: llAllowInventoryDrop(integer add) + void llAllowInventoryDrop(int add); + //wiki: vector llGetSunDirection() + LSL_Types.Vector3 llGetSunDirection(); + //wiki: vector llGetTextureOffset(integer face) + LSL_Types.Vector3 llGetTextureOffset(int face); + //wiki: vector llGetTextureScale(integer side) + LSL_Types.Vector3 llGetTextureScale(int side); + //wiki: double llGetTextureRot(integer side) + double llGetTextureRot(int side); + //wiki: integer llSubStringIndex(string source, string pattern) + int llSubStringIndex(string source, string pattern); + //wiki: key llGetOwnerKey(key id) + string llGetOwnerKey(string id); + //wiki: vector llGetCenterOfMass() + LSL_Types.Vector3 llGetCenterOfMass(); + //wiki: list llListSort(list src, integer stride, integer ascending) + LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending); + //integer llGetListLength(list src) + int llGetListLength(LSL_Types.list src); + //wiki: integer llList2Integer(list src, integer index) + int llList2Integer(LSL_Types.list src, int index); + //wiki: double llList2double(list src, integer index) + double llList2Float(LSL_Types.list src, int index); + double osList2Double(LSL_Types.list src, int index); + //wiki: string llList2String(list src, integer index) + string llList2String(LSL_Types.list src, int index); + //wiki: key llList2Key(list src, integer index) + string llList2Key(LSL_Types.list src, int index); + //wiki: vector llList2Vector(list src, integer index) + LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index); + //wiki rotation llList2Rot(list src, integer index) + LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index); + //wiki: list llList2List(list src, integer start, integer end) + LSL_Types.list llList2List(LSL_Types.list src, int start, int end); + //wiki: llDeleteSubList(list src, integer start, integer end) + LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end); + //wiki: integer llGetListEntryType( list src, integer index ) + int llGetListEntryType(LSL_Types.list src, int index); + //wiki: string llList2CSV( list src ) + string llList2CSV(LSL_Types.list src); + //wiki: list llCSV2List( string src ) + LSL_Types.list llCSV2List(string src); + //wiki: list llListRandomize( list src, integer stride ) + LSL_Types.list llListRandomize(LSL_Types.list src, int stride); + //wiki: list llList2ListStrided( list src, integer start, integer end, integer stride ) + LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride); + //wiki: vector llGetRegionCorner( ) + LSL_Types.Vector3 llGetRegionCorner(); + //wiki: list llListInsertList( list dest, list src, integer start ) + LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start); + //wiki: integer llListFindList( list src, list test ) + int llListFindList(LSL_Types.list src, LSL_Types.list test); + //wiki: string llGetObjectName() + string llGetObjectName(); + //wiki: llSetObjectName(string name) + void llSetObjectName(string name); + //wiki: string llGetDate() + string llGetDate(); + //wiki: integer llEdgeOfWorld(vector pos, vector dir) + int llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir); + //wiki: integer llGetAgentInfo(key id) + int llGetAgentInfo(string id); + //wiki: llAdjustSoundVolume(double volume) + void llAdjustSoundVolume(double volume); + //wiki: llSetSoundQueueing(integer queue) + void llSetSoundQueueing(int queue); + //wiki: llSetSoundRadius(double radius) + void llSetSoundRadius(double radius); + //wiki: string llKey2Name(key id) + string llKey2Name(string id); + //wiki: llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, double start, double length, double rate) + void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate); + //wiki: llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) + void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, + LSL_Types.Vector3 bottom_south_west); + + //wiki: llEjectFromLand(key pest) + void llEjectFromLand(string pest); + LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers); + //wiki: integer llOverMyLand(key id) + int llOverMyLand(string id); + //wiki: key llGetLandOwnerAt(vector pos) + string llGetLandOwnerAt(LSL_Types.Vector3 pos); + //wiki: key llGetNotecardLine(string name, integer line) + string llGetNotecardLine(string name, int line); + //wiki: vector llGetAgentSize(key id) + LSL_Types.Vector3 llGetAgentSize(string id); + //wiki: integer llSameGroup(key agent) + int llSameGroup(string agent); + //wiki: llUnSit(key id) + void llUnSit(string id); + //wiki: vector llGroundSlope(vector offset) + LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset); + //wiki: vector llGroundNormal(vector offset) + LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset); + //wiki: vector llGroundContour(vector offset) + LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset); + //wiki: integer llGetAttached() + int llGetAttached(); + //wiki: integer llGetFreeMemory() + int llGetFreeMemory(); + //wiki: string llGetRegionName() + string llGetRegionName(); + //wiki: double llGetRegionTimeDilation() + double llGetRegionTimeDilation(); + //wiki: double llGetRegionFPS() + double llGetRegionFPS(); + //wiki: llParticleSystem(List rules + void llParticleSystem(LSL_Types.list rules); + //wiki: llGroundRepel(double height, integer water, double tau) + void llGroundRepel(double height, int water, double tau); + void llGiveInventoryList(); + //wiki: llSetVehicleType(integer type) + void llSetVehicleType(int type); + //wiki: llSetVehicledoubleParam(integer param, double value) + void llSetVehicledoubleParam(int param, double value); + //wiki: llSetVehicleVectorParam(integer param, vector vec) + void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec); + //wiki: llSetVehicleRotationParam(integer param, rotation rot) + void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot); + //wiki: llSetVehicleFlags(integer flags) + void llSetVehicleFlags(int flags); + //wiki: llRemoveVehicleFlags(integer flags) + void llRemoveVehicleFlags(int flags); + //wiki: llSitTarget(vector offset, rotation rot) + void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot); + //wiki key llAvatarOnSitTarget() + string llAvatarOnSitTarget(); + //wiki: llAddToLandPassList(key avatar, double hours) + void llAddToLandPassList(string avatar, double hours); + //wiki: llSetTouchText(string text) + void llSetTouchText(string text); + //wiki: llSetSitText(string text) + void llSetSitText(string text); + //wiki: llSetCameraEyeOffset(vector offset) + void llSetCameraEyeOffset(LSL_Types.Vector3 offset); + //wiki: llSeteCameraAtOffset(vector offset) + void llSetCameraAtOffset(LSL_Types.Vector3 offset); + // + string llDumpList2String(LSL_Types.list src, string seperator); + //wiki: integer llScriptDanger(vector pos) + void llScriptDanger(LSL_Types.Vector3 pos); + //wiki: llDialog( key avatar, string message, list buttons, integer chat_channel ) + void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel); + //wiki: llVolumeDetect(integer detect) + void llVolumeDetect(int detect); + //wiki: llResetOtherScript(string name) + void llResetOtherScript(string name); + //wiki: integer llGetScriptState(string name) + int llGetScriptState(string name); + //wiki: (deprecated) + void llRemoteLoadScript(); + //wiki: llSetRemoteScriptAccessPin(integer pin) + void llSetRemoteScriptAccessPin(int pin); + //wiki: llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param) + void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param); + //wiki: llOpenRemoteDataChannel() + void llOpenRemoteDataChannel(); + //wiki: key llSendRemoteData(key channel, string dest, integer idata, string sdata) + string llSendRemoteData(string channel, string dest, int idata, string sdata); + //wiki: llRemoteDataReply(key channel, key message_id, string sdata, integer idata) + void llRemoteDataReply(string channel, string message_id, string sdata, int idata); + //wiki: llCloseRemoteDataChannel(key channel) + void llCloseRemoteDataChannel(string channel); + //wiki: string llMD5String(string src, integer nonce) + string llMD5String(string src, int nonce); + //wiki: llSetPrimitiveParams( list rules ) + void llSetPrimitiveParams(LSL_Types.list rules); + //wiki: string llStringToBase64(string str) + string llStringToBase64(string str); + //wiki: string llBase64ToString(string str) + string llBase64ToString(string str); + //wiki: (deprecated) + void llXorBase64Strings(); + //wiki: llRemoteDataSetRegion() + void llRemoteDataSetRegion(); + //wiki: double llLog10(double val) + double llLog10(double val); + //wiki: double llLog(double val) + double llLog(double val); + //wiki: list llGetAnimationList( key id ) + LSL_Types.list llGetAnimationList(string id); + //wiki: llSetParcelMusicURL(string url) + void llSetParcelMusicURL(string url); + //wiki: vector llGetRootPosition() + LSL_Types.Vector3 llGetRootPosition(); + //wiki: rotation llGetRootRotation() + LSL_Types.Quaternion llGetRootRotation(); + //wiki: string llGetObjectDesc() + string llGetObjectDesc(); + //wiki: llSetObjectDesc(string desc) + void llSetObjectDesc(string desc); + //wiki: key llGetCreator() + string llGetCreator(); + //wiki: string llGetTimestamp() + string llGetTimestamp(); + //wiki: llSetLinkAlpha(integer linknumber, double alpha, integer face) + void llSetLinkAlpha(int linknumber, double alpha, int face); + //wiki: integer llGetNumberOfPrims() + int llGetNumberOfPrims(); + //wiki: key llGetNumberOfNotecardLines(string name) + string llGetNumberOfNotecardLines(string name); + //wiki: list llGetBoundingBox( key object ) + LSL_Types.list llGetBoundingBox(string obj); + //wiki: vector llGetGeometricCenter() + LSL_Types.Vector3 llGetGeometricCenter(); + void llGetPrimitiveParams(); + //wiki: string llIntegerToBase64(integer number) + string llIntegerToBase64(int number); + //wiki integer llBase64ToInteger(string str) + int llBase64ToInteger(string str); + //wiki: double llGetGMTclock() + double llGetGMTclock(); + //wiki: string llGetSimulatorHostname() + string llGetSimulatorHostname(); + //llSetLocalRot(rotation rot) + void llSetLocalRot(LSL_Types.Quaternion rot); + //wiki: list llParseStringKeepNulls( string src, list separators, list spacers ) + LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers); + //wiki: llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, integer param) + void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, + LSL_Types.Quaternion rot, int param); + + //wiki: integer llGetObjectPermMask(integer mask) + int llGetObjectPermMask(int mask); + //wiki: llSetObjectPermMask(integer mask, integer value) + void llSetObjectPermMask(int mask, int value); + //wiki integer llGetInventoryPermMask(string item, integer mask) + void llGetInventoryPermMask(string item, int mask); + //wiki: llSetInventoryPermMask(string item, integer mask, integer value) + void llSetInventoryPermMask(string item, int mask, int value); + //wiki: key llGetInventoryCreator(string item) + string llGetInventoryCreator(string item); + //wiki: llOwnerSay(string msg) + void llOwnerSay(string msg); + //wiki: key llRequestSimulatorData(string simulator, integer data) + void llRequestSimulatorData(string simulator, int data); + //wiki: llForceMouselook(integer mouselook) + void llForceMouselook(int mouselook); + //wiki: double llGetObjectMass(key id) + double llGetObjectMass(string id); + LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end); + //wiki: llLoadURL(key avatar_id, string message, string url) + void llLoadURL(string avatar_id, string message, string url); + //wiki: llParcelMediaCommandList( list commandList ) + void llParcelMediaCommandList(LSL_Types.list commandList); + void llParcelMediaQuery(); + //wiki integer llModPow(integer a, integer b, integer c) + int llModPow(int a, int b, int c); + //wiki: integer llGetInventoryType(string name) + int llGetInventoryType(string name); + //wiki: llSetPayPrice( integer price, list quick_pay_buttons ) + void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons); + //wiki: vector llGetCameraPos() + LSL_Types.Vector3 llGetCameraPos(); + //wiki rotation llGetCameraRot() + LSL_Types.Quaternion llGetCameraRot(); + //wiki: (deprecated) + void llSetPrimURL(); + //wiki: (deprecated) + void llRefreshPrimURL(); + //wiki: string llEscapeURL(string url) + string llEscapeURL(string url); + //wiki: string llUnescapeURL(string url) + string llUnescapeURL(string url); + //wiki: llMapDestination(string simname, vector pos, vector look_at) + void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at); + //wiki: llAddToLandBanList(key avatar, double hours) + void llAddToLandBanList(string avatar, double hours); + //wiki: llRemoveFromLandPassList(key avatar) + void llRemoveFromLandPassList(string avatar); + //wiki: llRemoveFromLandBanList(key avatar) + void llRemoveFromLandBanList(string avatar); + //wiki: llSetCameraParams( list rules ) + void llSetCameraParams(LSL_Types.list rules); + //wiki: llClearCameraParams() + void llClearCameraParams(); + //wiki: double llListStatistics( integer operation, list src ) + double llListStatistics(int operation, LSL_Types.list src); + //wiki: integer llGetUnixTime() + int llGetUnixTime(); + //wiki: integer llGetParcelFlags(vector pos) + int llGetParcelFlags(LSL_Types.Vector3 pos); + //wiki: integer llGetRegionFlags() + int llGetRegionFlags(); + //wiki: string llXorBase64StringsCorrect(string str1, string str2) + string llXorBase64StringsCorrect(string str1, string str2); + string llHTTPRequest(string url, LSL_Types.list parameters, string body); + //wiki: llResetLandBanList() + void llResetLandBanList(); + //wiki: llResetLandPassList() + void llResetLandPassList(); + //wiki integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide) + int llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide); + //wiki: list llGetParcelPrimOwners( vector pos ) + LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos); + //wiki: integer llGetObjectPrimCount(key object_id) + int llGetObjectPrimCount(string object_id); + //wiki: integer llGetParcelMaxPrims( vector pos, integer sim_wide ) + int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide); + //wiki list llGetParcelDetails(vector pos, list params) + LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param); + string llStringTrim(string src, int type); + //OpenSim functions + string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer); + double osTerrainGetHeight(int x, int y); + int osTerrainSetHeight(int x, int y, double val); + int osRegionRestart(double seconds); + void osRegionNotice(string msg); + bool osConsoleCommand(string Command); + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs index 8c88414cf6..f3e57c4df1 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs @@ -1,792 +1,1070 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Text.RegularExpressions; - -namespace OpenSim.Region.ScriptEngine.Common -{ - [Serializable] - public partial class LSL_Types - { - - // Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain - - [Serializable] - public struct Vector3 - { - public double x; - public double y; - public double z; - - #region Constructors - - public Vector3(Vector3 vector) - { - x = (float)vector.x; - y = (float)vector.y; - z = (float)vector.z; - } - - public Vector3(double X, double Y, double Z) - { - x = X; - y = Y; - z = Z; - } - - public Vector3(string str) - { - str = str.Replace('<', ' '); - str = str.Replace('>', ' '); - string[] tmps = str.Split(new Char[] { ',', '<', '>' }); - bool res; - res = Double.TryParse(tmps[0], out x); - res = res & Double.TryParse(tmps[1], out y); - res = res & Double.TryParse(tmps[2], out z); - } - - #endregion - - #region Overriders - - public override string ToString() - { - return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ">"; - } - - public static bool operator ==(Vector3 lhs, Vector3 rhs) - { - return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); - } - - public static bool operator !=(Vector3 lhs, Vector3 rhs) - { - return !(lhs == rhs); - } - - public override int GetHashCode() - { - return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode()); - } - - public override bool Equals(object o) - { - if (!(o is Vector3)) return false; - - Vector3 vector = (Vector3)o; - - return (x == vector.x && x == vector.x && z == vector.z); - } - - #endregion - - #region Vector & Vector Math - - // Vector-Vector Math - public static Vector3 operator +(Vector3 lhs, Vector3 rhs) - { - return new Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); - } - - public static Vector3 operator -(Vector3 lhs, Vector3 rhs) - { - return new Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); - } - - public static Vector3 operator *(Vector3 lhs, Vector3 rhs) - { - return new Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); - } - - public static Vector3 operator %(Vector3 v1, Vector3 v2) - { - //Cross product - Vector3 tv; - tv.x = (v1.y * v2.z) - (v1.z * v2.y); - tv.y = (v1.z * v2.x) - (v1.x * v2.z); - tv.z = (v1.x * v2.y) - (v1.y * v2.x); - return tv; - } - - #endregion - - #region Vector & Float Math - - // Vector-Float and Float-Vector Math - public static Vector3 operator *(Vector3 vec, float val) - { - return new Vector3(vec.x * val, vec.y * val, vec.z * val); - } - - public static Vector3 operator *(float val, Vector3 vec) - { - return new Vector3(vec.x * val, vec.y * val, vec.z * val); - } - - public static Vector3 operator /(Vector3 v, float f) - { - v.x = v.x / f; - v.y = v.y / f; - v.z = v.z / f; - return v; - } - - #endregion - - #region Vector & Double Math - - public static Vector3 operator *(Vector3 vec, double val) - { - return new Vector3(vec.x * val, vec.y * val, vec.z * val); - } - - public static Vector3 operator *(double val, Vector3 vec) - { - return new Vector3(vec.x * val, vec.y * val, vec.z * val); - } - - public static Vector3 operator /(Vector3 v, double f) - { - v.x = v.x / f; - v.y = v.y / f; - v.z = v.z / f; - return v; - } - - #endregion - - #region Vector & Rotation Math - - // Vector-Rotation Math - public static Vector3 operator *(Vector3 v, Quaternion r) - { - Quaternion vq = new Quaternion(v.x, v.y, v.z, 0); - Quaternion nq = new Quaternion(-r.x, -r.y, -r.z, r.s); - - Quaternion result = (r * vq) * nq; - - return new Vector3(result.x, result.y, result.z); - } - - // I *think* this is how it works.... - public static Vector3 operator /(Vector3 vec, Quaternion quat) - { - quat.s = -quat.s; - Quaternion vq = new Quaternion(vec.x, vec.y, vec.z, 0); - Quaternion nq = new Quaternion(-quat.x, -quat.y, -quat.z, quat.s); - - Quaternion result = (quat * vq) * nq; - - return new Vector3(result.x, result.y, result.z); - } - - #endregion - - #region Static Helper Functions - - public static double Dot(Vector3 v1, Vector3 v2) - { - return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); - } - - public static Vector3 Cross(Vector3 v1, Vector3 v2) - { - return new Vector3 - ( - v1.y * v2.z - v1.z * v2.y, - v1.z * v2.x - v1.x * v2.z, - v1.x * v2.y - v1.y * v2.x - ); - } - - public static float Mag(Vector3 v) - { - return (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - } - - public static Vector3 Norm(Vector3 vector) - { - float mag = Mag(vector); - return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag); - } - - #endregion - } - - [Serializable] - public struct Quaternion - { - public double x; - public double y; - public double z; - public double s; - - #region Constructors - - public Quaternion(Quaternion Quat) - { - x = (float)Quat.x; - y = (float)Quat.y; - z = (float)Quat.z; - s = (float)Quat.s; - } - - public Quaternion(double X, double Y, double Z, double S) - { - x = X; - y = Y; - z = Z; - s = S; - } - - public Quaternion(string str) - { - str = str.Replace('<', ' '); - str = str.Replace('>', ' '); - string[] tmps = str.Split(new Char[] { ',', '<', '>' }); - bool res; - res = Double.TryParse(tmps[0], out x); - res = res & Double.TryParse(tmps[1], out y); - res = res & Double.TryParse(tmps[2], out z); - res = res & Double.TryParse(tmps[3], out s); - } - - #endregion - - #region Overriders - - public override int GetHashCode() - { - return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ s.GetHashCode()); - } - - public override bool Equals(object o) - { - if (!(o is Quaternion)) return false; - - Quaternion quaternion = (Quaternion)o; - - return x == quaternion.x && y == quaternion.y && z == quaternion.z && s == quaternion.s; - } - - public override string ToString() - { - return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ", " + s.ToString() + ">"; - } - - public static bool operator ==(Quaternion lhs, Quaternion rhs) - { - // Return true if the fields match: - return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.s == rhs.s; - } - - public static bool operator !=(Quaternion lhs, Quaternion rhs) - { - return !(lhs == rhs); - } - - #endregion - - public static Quaternion operator *(Quaternion a, Quaternion b) - { - Quaternion c; - c.x = a.s * b.x + a.x * b.s + a.y * b.z - a.z * b.y; - c.y = a.s * b.y + a.y * b.s + a.z * b.x - a.x * b.z; - c.z = a.s * b.z + a.z * b.s + a.x * b.y - a.y * b.x; - c.s = a.s * b.s - a.x * b.x - a.y * b.y - a.z * b.z; - return c; - } - } - - [Serializable] - public class list - { - private object[] m_data; - - public list(params object[] args) - { - m_data = new object[args.Length]; - m_data = args; - } - - public int Length - { - get { return m_data.Length; } - } - - public object[] Data - { - get { return m_data; } - } - - public static list operator +(list a, list b) - { - object[] tmp; - tmp = new object[a.Length + b.Length]; - a.Data.CopyTo(tmp, 0); - b.Data.CopyTo(tmp, a.Length); - return new list(tmp); - } - - public list GetSublist(int start, int end) - { - Console.WriteLine("GetSublist(" + start.ToString() + "," + end.ToString() + ")"); - object[] ret; - // Take care of neg start or end's - if (start < 0) - { - start = m_data.Length + start; - } - if (end < 0) - { - end = m_data.Length + end; - } - - // Case start <= end - if (start <= end) - { - if (start >= m_data.Length) - { - return new list(); - } - if (end >= m_data.Length) - { - end = m_data.Length - 1; - } - ret = new object[end - start + 1]; - Array.Copy(m_data, start, ret, 0, end - start + 1); - return new list(ret); - } - else - { - if (start >= m_data.Length) - { - return GetSublist(0, end); - } - if (end >= m_data.Length) - { - return new list(); - } - // end < start - //ret = new object[m_data.Length - Math.Abs(end - start + 1)]; - //Array.Copy(m_data, 0, ret, m_data.Length - start, end + 1); - //Array.Copy(m_data, start, ret, 0, m_data.Length - start); - return GetSublist(0, end) + GetSublist(start, Data.Length - 1); - //return new list(ret); - } - } - - public string ToPrettyString() - { - string output; - if (m_data.Length == 0) - { - return "[]"; - } - output = "["; - foreach (object o in m_data) - { - if (o is System.String) - { - output = output + "\"" + o + "\", "; - } - else - { - output = output + o.ToString() + ", "; - } - } - output = output.Substring(0, output.Length - 2); - output = output + "]"; - return output; - } - - public override string ToString() - { - string output; - output = ""; - if (m_data.Length == 0) - { - return ""; - } - foreach (object o in m_data) - { - output = output + o.ToString(); - } - return output; - - } - - } - - // - // BELOW IS WORK IN PROGRESS... IT WILL CHANGE, SO DON'T USE YET! :) - // - - public struct StringTest - { - // Our own little string - internal string actualString; - public static implicit operator bool(StringTest mString) - { - if (mString.actualString.Length == 0) - return true; - return false; - } - public override string ToString() - { - return actualString; - } - - } - - [Serializable] - public struct key - { - public string value; - - #region Constructors - public key(string s) - { - value = s; - } - - #endregion - - #region Methods - - static public bool Parse2Key(string s) - { - Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled); - if (isuuid.IsMatch(s)) - { - return true; - } - else - { - return false; - } - } - - #endregion - - #region Operators - - static public implicit operator System.Boolean(key k) - { - if (k.value.Length == 0) - { - return false; - } - - if (k.value == "00000000-0000-0000-0000-000000000000") - { - return false; - } - Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled); - if (isuuid.IsMatch(k.value)) - { - return true; - } - else - { - return false; - } - } - - static public implicit operator key(string s) - { - return new key(s); - } - - static public implicit operator System.String(key k) - { - return k.value; - } - - public static bool operator ==(key k1, key k2) - { - return k1.value == k2.value; - } - public static bool operator !=(key k1, key k2) - { - return k1.value != k2.value; - } - - #endregion - - #region Overriders - - public override bool Equals(object o) - { - if (o is String) - { - string s = (string)o; - return s == this.value; - } - if (o is key) - { - key k = (key)o; - return this.value == k.value; - } - return false; - } - - public override int GetHashCode() - { - return value.GetHashCode(); - } - - #endregion - } - - [Serializable] - public struct LSLString - { - public string m_string; - #region Constructors - public LSLString(string s) - { - m_string = s; - } - #endregion - - #region Operators - static public implicit operator System.Boolean(LSLString s) - { - if (s.m_string.Length == 0) - { - return false; - } - else - { - return true; - } - } - - static public implicit operator System.String(LSLString s) - { - return s.m_string; - } - - static public implicit operator LSLString(string s) - { - return new LSLString(s); - } - - // Commented out: - /* - [echo] Build Directory is /home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/bin/Debug - [csc] Compiling 5 files to '/home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/bin/Debug/OpenSim.Region.ScriptEngine.Common.dll'. - [csc] error CS0121: The call is ambiguous between the following methods or properties: `OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString.operator /(OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString, OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString)' and `string.operator /(string, string)' - [csc] /home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs(602,32): (Location of the symbol related to previous error) - [csc] /usr/lib/mono/2.0/mscorlib.dll (Location of the symbol related to previous error) - [csc] Compilation failed: 1 error(s), 0 warnings - */ - //public static bool operator ==(LSLString s1, LSLString s2) - //{ - // return s1.m_string == s2.m_string; - //} - //public static bool operator !=(LSLString s1, LSLString s2) - //{ - // return s1.m_string != s2.m_string; - //} - #endregion - - #region Overriders - public override bool Equals(object o) - { - if (o is String) - { - string s = (string)o; - return s == this.m_string; - } - if (o is key) - { - key k = (key)o; - return this.m_string == k.value; - } - if (o is LSLString) - { - LSLString s = (string)o; - return this.m_string == s; - } - return false; - } - - public override int GetHashCode() - { - return m_string.GetHashCode(); - } - - #endregion - - #region " Standard string functions " - //Clone,CompareTo,Contains - //CopyTo,EndsWith,Equals,GetEnumerator,GetHashCode,GetType,GetTypeCode - //IndexOf,IndexOfAny,Insert,IsNormalized,LastIndexOf,LastIndexOfAny - //Length,Normalize,PadLeft,PadRight,Remove,Replace,Split,StartsWith,Substring,ToCharArray,ToLowerInvariant - //ToString,ToUpper,ToUpperInvariant,Trim,TrimEnd,TrimStart - public bool Contains(string value) { return m_string.Contains(value); } - public int IndexOf(string value) { return m_string.IndexOf(value); } - public int Length { get { return m_string.Length; } } - - - #endregion - } - - [Serializable] - public struct LSLInteger - { - public int value; - - #region Constructors - public LSLInteger(int i) - { - value = i; - } - - public LSLInteger(double d) - { - value = (int)d; - } - - #endregion - static public implicit operator System.Int32(LSLInteger i) - { - return i.value; - } - - static public implicit operator System.Boolean(LSLInteger i) - { - if (i.value == 0) - { - return false; - } - else - { - return true; - } - } - - static public implicit operator LSLInteger(int i) - { - return new LSLInteger(i); - } - - static public implicit operator LSLInteger(double d) - { - return new LSLInteger(d); - } - - static public LSLInteger operator &(LSLInteger i1, LSLInteger i2) - { - int ret = i1.value & i2.value; - return ret; - } - - - //static public implicit operator System.Double(LSLInteger i) - //{ - // return (double)i.value; - //} - - #region Overriders - - public override string ToString() - { - return this.value.ToString(); - } - - #endregion - } - - [Serializable] - public struct LSLFloat - { - public double value; - - #region Constructors - public LSLFloat(int i) - { - this.value = (double)i; - } - - public LSLFloat(double d) - { - this.value = d; - } - - #endregion - - #region Operators - - static public implicit operator System.Double(LSLFloat f) - { - return f.value; - } - - //static public implicit operator System.Int32(LSLFloat f) - //{ - // return (int)f.value; - //} - - - static public implicit operator System.Boolean(LSLFloat f) - { - if (f.value == 0) - { - return false; - } - else - { - return true; - } - } - - static public implicit operator LSLFloat(int i) - { - return new LSLFloat(i); - } - - static public implicit operator LSLFloat(double d) - { - return new LSLFloat(d); - } - #endregion - - #region Overriders - public override string ToString() - { - return this.value.ToString(); - } - #endregion - } - - } -} +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Text.RegularExpressions; +using System.Collections; + +namespace OpenSim.Region.ScriptEngine.Common +{ + [Serializable] + public partial class LSL_Types + { + + // Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain + + [Serializable] + public struct Vector3 + { + public double x; + public double y; + public double z; + + #region Constructors + + public Vector3(Vector3 vector) + { + x = (float)vector.x; + y = (float)vector.y; + z = (float)vector.z; + } + + public Vector3(double X, double Y, double Z) + { + x = X; + y = Y; + z = Z; + } + + public Vector3(string str) + { + str = str.Replace('<', ' '); + str = str.Replace('>', ' '); + string[] tmps = str.Split(new Char[] { ',', '<', '>' }); + bool res; + res = Double.TryParse(tmps[0], out x); + res = res & Double.TryParse(tmps[1], out y); + res = res & Double.TryParse(tmps[2], out z); + } + + #endregion + + #region Overriders + + public override string ToString() + { + return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ">"; + } + + public static explicit operator string(Vector3 vec) + { + return "<" + vec.x.ToString() + ", " + vec.y.ToString() + ", " + vec.z.ToString() + ">"; + } + + public static bool operator ==(Vector3 lhs, Vector3 rhs) + { + return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); + } + + public static bool operator !=(Vector3 lhs, Vector3 rhs) + { + return !(lhs == rhs); + } + + public override int GetHashCode() + { + return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode()); + } + + public override bool Equals(object o) + { + if (!(o is Vector3)) return false; + + Vector3 vector = (Vector3)o; + + return (x == vector.x && x == vector.x && z == vector.z); + } + + #endregion + + #region Vector & Vector Math + + // Vector-Vector Math + public static Vector3 operator +(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); + } + + public static Vector3 operator -(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); + } + + public static Vector3 operator *(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); + } + + public static Vector3 operator %(Vector3 v1, Vector3 v2) + { + //Cross product + Vector3 tv; + tv.x = (v1.y * v2.z) - (v1.z * v2.y); + tv.y = (v1.z * v2.x) - (v1.x * v2.z); + tv.z = (v1.x * v2.y) - (v1.y * v2.x); + return tv; + } + + #endregion + + #region Vector & Float Math + + // Vector-Float and Float-Vector Math + public static Vector3 operator *(Vector3 vec, float val) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator *(float val, Vector3 vec) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator /(Vector3 v, float f) + { + v.x = v.x / f; + v.y = v.y / f; + v.z = v.z / f; + return v; + } + + #endregion + + #region Vector & Double Math + + public static Vector3 operator *(Vector3 vec, double val) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator *(double val, Vector3 vec) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator /(Vector3 v, double f) + { + v.x = v.x / f; + v.y = v.y / f; + v.z = v.z / f; + return v; + } + + #endregion + + #region Vector & Rotation Math + + // Vector-Rotation Math + public static Vector3 operator *(Vector3 v, Quaternion r) + { + Quaternion vq = new Quaternion(v.x, v.y, v.z, 0); + Quaternion nq = new Quaternion(-r.x, -r.y, -r.z, r.s); + + Quaternion result = (r * vq) * nq; + + return new Vector3(result.x, result.y, result.z); + } + + // I *think* this is how it works.... + public static Vector3 operator /(Vector3 vec, Quaternion quat) + { + quat.s = -quat.s; + Quaternion vq = new Quaternion(vec.x, vec.y, vec.z, 0); + Quaternion nq = new Quaternion(-quat.x, -quat.y, -quat.z, quat.s); + + Quaternion result = (quat * vq) * nq; + + return new Vector3(result.x, result.y, result.z); + } + + #endregion + + #region Static Helper Functions + + public static double Dot(Vector3 v1, Vector3 v2) + { + return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); + } + + public static Vector3 Cross(Vector3 v1, Vector3 v2) + { + return new Vector3 + ( + v1.y * v2.z - v1.z * v2.y, + v1.z * v2.x - v1.x * v2.z, + v1.x * v2.y - v1.y * v2.x + ); + } + + public static float Mag(Vector3 v) + { + return (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + } + + public static Vector3 Norm(Vector3 vector) + { + float mag = Mag(vector); + return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag); + } + + #endregion + } + + [Serializable] + public struct Quaternion + { + public double x; + public double y; + public double z; + public double s; + + #region Constructors + + public Quaternion(Quaternion Quat) + { + x = (float)Quat.x; + y = (float)Quat.y; + z = (float)Quat.z; + s = (float)Quat.s; + } + + public Quaternion(double X, double Y, double Z, double S) + { + x = X; + y = Y; + z = Z; + s = S; + } + + public Quaternion(string str) + { + str = str.Replace('<', ' '); + str = str.Replace('>', ' '); + string[] tmps = str.Split(new Char[] { ',', '<', '>' }); + bool res; + res = Double.TryParse(tmps[0], out x); + res = res & Double.TryParse(tmps[1], out y); + res = res & Double.TryParse(tmps[2], out z); + res = res & Double.TryParse(tmps[3], out s); + } + + #endregion + + #region Overriders + + public override int GetHashCode() + { + return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ s.GetHashCode()); + } + + public override bool Equals(object o) + { + if (!(o is Quaternion)) return false; + + Quaternion quaternion = (Quaternion)o; + + return x == quaternion.x && y == quaternion.y && z == quaternion.z && s == quaternion.s; + } + + public override string ToString() + { + return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ", " + s.ToString() + ">"; + } + + public static explicit operator string(Quaternion r) + { + return "<" + r.x.ToString() + ", " + r.y.ToString() + ", " + r.z.ToString() + ", " + r.s.ToString() + ">"; + } + + public static bool operator ==(Quaternion lhs, Quaternion rhs) + { + // Return true if the fields match: + return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.s == rhs.s; + } + + public static bool operator !=(Quaternion lhs, Quaternion rhs) + { + return !(lhs == rhs); + } + + #endregion + + public static Quaternion operator *(Quaternion a, Quaternion b) + { + Quaternion c; + c.x = a.s * b.x + a.x * b.s + a.y * b.z - a.z * b.y; + c.y = a.s * b.y + a.y * b.s + a.z * b.x - a.x * b.z; + c.z = a.s * b.z + a.z * b.s + a.x * b.y - a.y * b.x; + c.s = a.s * b.s - a.x * b.x - a.y * b.y - a.z * b.z; + return c; + } + } + + [Serializable] + public class list + { + private object[] m_data; + + public list(params object[] args) + { + m_data = new object[args.Length]; + m_data = args; + } + + public int Length + { + get { return m_data.Length; } + } + + public object[] Data + { + get { return m_data; } + } + + public static list operator +(list a, list b) + { + object[] tmp; + tmp = new object[a.Length + b.Length]; + a.Data.CopyTo(tmp, 0); + b.Data.CopyTo(tmp, a.Length); + return new list(tmp); + } + + public void Add(object o) + { + object[] tmp; + tmp = new object[m_data.Length + 1]; + m_data.CopyTo(tmp, 0); + tmp[m_data.Length] = o; + m_data = tmp; + } + + public bool Contains(object o) + { + bool ret = false; + foreach (object i in Data) + { + if (i == o) + { + ret = true; + break; + } + } + return ret; + } + + public list GetSublist(int start, int end) + { + Console.WriteLine("GetSublist(" + start.ToString() + "," + end.ToString() + ")"); + object[] ret; + // Take care of neg start or end's + if (start < 0) + { + start = m_data.Length + start; + } + if (end < 0) + { + end = m_data.Length + end; + } + + // Case start <= end + if (start <= end) + { + if (start >= m_data.Length) + { + return new list(); + } + if (end >= m_data.Length) + { + end = m_data.Length - 1; + } + ret = new object[end - start + 1]; + Array.Copy(m_data, start, ret, 0, end - start + 1); + return new list(ret); + } + else + { + if (start >= m_data.Length) + { + return GetSublist(0, end); + } + if (end >= m_data.Length) + { + return new list(); + } + // end < start + //ret = new object[m_data.Length - Math.Abs(end - start + 1)]; + //Array.Copy(m_data, 0, ret, m_data.Length - start, end + 1); + //Array.Copy(m_data, start, ret, 0, m_data.Length - start); + return GetSublist(0, end) + GetSublist(start, Data.Length - 1); + //return new list(ret); + } + } + + #region CSV Methods + + public static list FromCSV(string csv) + { + return new list(csv.Split(',')); + } + + public string ToCSV() + { + string ret = ""; + foreach(object o in this.Data) + { + if(ret == "") + { + ret = o.ToString(); + } + else + { + ret = ret + ", " + o.ToString(); + } + } + return ret; + } + #endregion + + #region Statistic Methods + + public double Min() + { + double minimum = double.PositiveInfinity; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + if (entry < minimum) minimum = entry; + } + } + return minimum; + } + + public double Max() + { + double maximum = double.NegativeInfinity; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + if (entry > maximum) maximum = entry; + } + } + return maximum; + } + + public double Range() + { + return (this.Max() / this.Min()); + } + + public int NumericLength() + { + int count = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + count++; + } + } + return count; + } + + public static list ToDoubleList(list src) + { + list ret = new list(); + double entry; + for (int i = 0; i < src.Data.Length - 1; i++) + { + if (double.TryParse(src.Data[i].ToString(), out entry)) + { + ret.Add(entry); + } + } + return ret; + } + + public double Sum() + { + double sum = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + sum = sum + entry; + } + } + return sum; + } + + public double SumSqrs() + { + double sum = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + sum = sum + Math.Pow(entry, 2); + } + } + return sum; + } + + public double Mean() + { + return (this.Sum() / this.NumericLength()); + } + + public void NumericSort() + { + IComparer Numeric = new NumericComparer(); + Array.Sort(Data, Numeric); + } + + public void AlphaSort() + { + IComparer Alpha = new AlphaCompare(); + Array.Sort(Data, Alpha); + } + + public double Median() + { + return Qi(0.5); + } + + public double GeometricMean() + { + double ret = 1.0; + list nums = list.ToDoubleList(this); + for (int i = 0; i < nums.Data.Length; i++) + { + ret *= (double)nums.Data[i]; + } + return Math.Exp(Math.Log(ret) / (double)nums.Data.Length); + } + + public double HarmonicMean() + { + double ret = 0.0; + list nums = list.ToDoubleList(this); + for (int i = 0; i < nums.Data.Length; i++) + { + ret += 1.0 / (double)nums.Data[i]; + } + return ((double)nums.Data.Length / ret); + } + + public double Variance() + { + double s = 0; + list num = list.ToDoubleList(this); + for (int i = 0; i < num.Data.Length; i++) + { + s += Math.Pow((double)num.Data[i], 2); + } + return (s - num.Data.Length * Math.Pow(num.Mean(), 2)) / (num.Data.Length - 1); + } + + public double StdDev() + { + return Math.Sqrt(this.Variance()); + } + + public double Qi(double i) + { + list j = this; + j.NumericSort(); + double ret; + if (Math.Ceiling(this.Length * i) == this.Length * i) + { + return (double)((double)j.Data[(int)(this.Length * i - 1)] + (double)j.Data[(int)(this.Length * i)]) / 2; + } + else + { + return (double)j.Data[((int)(Math.Ceiling(this.Length * i))) - 1]; + } + } + + #endregion + + public string ToPrettyString() + { + string output; + if (m_data.Length == 0) + { + return "[]"; + } + output = "["; + foreach (object o in m_data) + { + if (o is System.String) + { + output = output + "\"" + o + "\", "; + } + else + { + output = output + o.ToString() + ", "; + } + } + output = output.Substring(0, output.Length - 2); + output = output + "]"; + return output; + } + + public class AlphaCompare : IComparer + { + int IComparer.Compare(object x, object y) + { + return string.Compare(x.ToString(), y.ToString()); + } + } + + public class NumericComparer : IComparer + { + int IComparer.Compare(object x, object y) + { + double a; + double b; + if (!double.TryParse(x.ToString(), out a)) + { + a = 0.0; + } + if (!double.TryParse(y.ToString(), out b)) + { + b = 0.0; + } + if (a < b) + { + return -1; + } + else if (a == b) + { + return 0; + } + else + { + return 1; + } + } + } + + public override string ToString() + { + string output; + output = String.Empty; + if (m_data.Length == 0) + { + return String.Empty; + } + foreach (object o in m_data) + { + output = output + o.ToString(); + } + return output; + + } + + public static explicit operator string(list l) + { + string output; + output = String.Empty; + if (l.m_data.Length == 0) + { + return String.Empty; + } + foreach (object o in l.m_data) + { + output = output + o.ToString(); + } + return output; + } + } + + // + // BELOW IS WORK IN PROGRESS... IT WILL CHANGE, SO DON'T USE YET! :) + // + + public struct StringTest + { + // Our own little string + internal string actualString; + public static implicit operator bool(StringTest mString) + { + if (mString.actualString.Length == 0) + return true; + return false; + } + public override string ToString() + { + return actualString; + } + + } + + [Serializable] + public struct key + { + public string value; + + #region Constructors + public key(string s) + { + value = s; + } + + #endregion + + #region Methods + + static public bool Parse2Key(string s) + { + Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled); + if (isuuid.IsMatch(s)) + { + return true; + } + else + { + return false; + } + } + + #endregion + + #region Operators + + static public implicit operator System.Boolean(key k) + { + if (k.value.Length == 0) + { + return false; + } + + if (k.value == "00000000-0000-0000-0000-000000000000") + { + return false; + } + Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled); + if (isuuid.IsMatch(k.value)) + { + return true; + } + else + { + return false; + } + } + + static public implicit operator key(string s) + { + return new key(s); + } + + static public implicit operator System.String(key k) + { + return k.value; + } + + public static bool operator ==(key k1, key k2) + { + return k1.value == k2.value; + } + public static bool operator !=(key k1, key k2) + { + return k1.value != k2.value; + } + + #endregion + + #region Overriders + + public override bool Equals(object o) + { + if (o is String) + { + string s = (string)o; + return s == this.value; + } + if (o is key) + { + key k = (key)o; + return this.value == k.value; + } + return false; + } + + public override int GetHashCode() + { + return value.GetHashCode(); + } + + #endregion + } + + [Serializable] + public struct LSLString + { + public string m_string; + #region Constructors + public LSLString(string s) + { + m_string = s; + } + #endregion + + #region Operators + static public implicit operator System.Boolean(LSLString s) + { + if (s.m_string.Length == 0) + { + return false; + } + else + { + return true; + } + } + + static public implicit operator System.String(LSLString s) + { + return s.m_string; + } + + static public implicit operator LSLString(string s) + { + return new LSLString(s); + } + + // Commented out: + /* + [echo] Build Directory is /home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/bin/Debug + [csc] Compiling 5 files to '/home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/bin/Debug/OpenSim.Region.ScriptEngine.Common.dll'. + [csc] error CS0121: The call is ambiguous between the following methods or properties: `OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString.operator /(OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString, OpenSim.Region.ScriptEngine.Common.LSL_Types.LSLString)' and `string.operator /(string, string)' + [csc] /home/tedd/opensim/trunk/OpenSim/Region/ScriptEngine/Common/LSL_Types.cs(602,32): (Location of the symbol related to previous error) + [csc] /usr/lib/mono/2.0/mscorlib.dll (Location of the symbol related to previous error) + [csc] Compilation failed: 1 error(s), 0 warnings + */ + //public static bool operator ==(LSLString s1, LSLString s2) + //{ + // return s1.m_string == s2.m_string; + //} + //public static bool operator !=(LSLString s1, LSLString s2) + //{ + // return s1.m_string != s2.m_string; + //} + #endregion + + #region Overriders + public override bool Equals(object o) + { + if (o is String) + { + string s = (string)o; + return s == this.m_string; + } + if (o is key) + { + key k = (key)o; + return this.m_string == k.value; + } + if (o is LSLString) + { + LSLString s = (string)o; + return this.m_string == s; + } + return false; + } + + public override int GetHashCode() + { + return m_string.GetHashCode(); + } + + #endregion + + #region " Standard string functions " + //Clone,CompareTo,Contains + //CopyTo,EndsWith,Equals,GetEnumerator,GetHashCode,GetType,GetTypeCode + //IndexOf,IndexOfAny,Insert,IsNormalized,LastIndexOf,LastIndexOfAny + //Length,Normalize,PadLeft,PadRight,Remove,Replace,Split,StartsWith,Substring,ToCharArray,ToLowerInvariant + //ToString,ToUpper,ToUpperInvariant,Trim,TrimEnd,TrimStart + public bool Contains(string value) { return m_string.Contains(value); } + public int IndexOf(string value) { return m_string.IndexOf(value); } + public int Length { get { return m_string.Length; } } + + + #endregion + } + + [Serializable] + public struct LSLInteger + { + public int value; + + #region Constructors + public LSLInteger(int i) + { + value = i; + } + + public LSLInteger(double d) + { + value = (int)d; + } + + #endregion + static public implicit operator System.Int32(LSLInteger i) + { + return i.value; + } + + static public implicit operator System.Boolean(LSLInteger i) + { + if (i.value == 0) + { + return false; + } + else + { + return true; + } + } + + static public implicit operator LSLInteger(int i) + { + return new LSLInteger(i); + } + + static public implicit operator LSLInteger(double d) + { + return new LSLInteger(d); + } + + static public LSLInteger operator &(LSLInteger i1, LSLInteger i2) + { + int ret = i1.value & i2.value; + return ret; + } + + + //static public implicit operator System.Double(LSLInteger i) + //{ + // return (double)i.value; + //} + + #region Overriders + + public override string ToString() + { + return this.value.ToString(); + } + + #endregion + } + + [Serializable] + public struct LSLFloat + { + public double value; + + #region Constructors + public LSLFloat(int i) + { + this.value = (double)i; + } + + public LSLFloat(double d) + { + this.value = d; + } + + #endregion + + #region Operators + + static public implicit operator System.Double(LSLFloat f) + { + return f.value; + } + + //static public implicit operator System.Int32(LSLFloat f) + //{ + // return (int)f.value; + //} + + + static public implicit operator System.Boolean(LSLFloat f) + { + if (f.value == 0) + { + return false; + } + else + { + return true; + } + } + + static public implicit operator LSLFloat(int i) + { + return new LSLFloat(i); + } + + static public implicit operator LSLFloat(double d) + { + return new LSLFloat(d); + } + #endregion + + #region Overriders + public override string ToString() + { + return this.value.ToString(); + } + #endregion + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Common/Properties/AssemblyInfo.cs index 977df827ca..c36c6db1ac 100644 --- a/OpenSim/Region/ScriptEngine/Common/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ScriptEngine/Common/Properties/AssemblyInfo.cs @@ -1,36 +1,64 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly : AssemblyTitle("OpenSim.Region.ScriptEngine.Common")] -[assembly : AssemblyDescription("")] -[assembly : AssemblyConfiguration("")] -[assembly : AssemblyCompany("")] -[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.Common")] -[assembly : AssemblyCopyright("Copyright © 2007")] -[assembly : AssemblyTrademark("")] -[assembly : AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly : ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly : Guid("0bf07c53-ae51-487f-a907-e9b30c251602")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// - -[assembly : AssemblyVersion("1.0.0.0")] -[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly : AssemblyTitle("OpenSim.Region.ScriptEngine.Common")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.Common")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2008")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly : ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly : Guid("0bf07c53-ae51-487f-a907-e9b30c251602")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs similarity index 80% rename from OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs rename to OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs index 07ca63835d..23dec6ab03 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs @@ -1,238 +1,254 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine -{ - public class AppDomainManager - { - - // - // This class does AppDomain handling and loading/unloading of scripts in it. - // It is instanced in "ScriptEngine" and controlled from "ScriptManager" - // - // 1. Create a new AppDomain if old one is full (or doesn't exist) - // 2. Load scripts into AppDomain - // 3. Unload scripts from AppDomain (stopping them and marking them as inactive) - // 4. Unload AppDomain completely when all scripts in it has stopped - // - - - private int maxScriptsPerAppDomain = 1; - - /// - /// Internal list of all AppDomains - /// - private List appDomains = new List(); - - /// - /// Structure to keep track of data around AppDomain - /// - private class AppDomainStructure - { - /// - /// The AppDomain itself - /// - public AppDomain CurrentAppDomain; - - /// - /// Number of scripts loaded into AppDomain - /// - public int ScriptsLoaded; - - /// - /// Number of dead scripts - /// - public int ScriptsWaitingUnload; - } - - /// - /// Current AppDomain - /// - private AppDomainStructure currentAD; - - private object getLock = new object(); // Mutex - private object freeLock = new object(); // Mutex - - //private ScriptEngine m_scriptEngine; - //public AppDomainManager(ScriptEngine scriptEngine) - public AppDomainManager() - { - //m_scriptEngine = scriptEngine; - } - - /// - /// Find a free AppDomain, creating one if necessary - /// - /// Free AppDomain - private AppDomainStructure GetFreeAppDomain() - { - Console.WriteLine("Finding free AppDomain"); - lock (getLock) - { - // Current full? - if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) - { - // Add it to AppDomains list and empty current - appDomains.Add(currentAD); - currentAD = null; - } - // No current - if (currentAD == null) - { - // Create a new current AppDomain - currentAD = new AppDomainStructure(); - currentAD.CurrentAppDomain = PrepareNewAppDomain(); - } - - Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded); - return currentAD; - } // lock - } - - private int AppDomainNameCount; - - /// - /// Create and prepare a new AppDomain for scripts - /// - /// The new AppDomain - private AppDomain PrepareNewAppDomain() - { - // Create and prepare a new AppDomain - AppDomainNameCount++; - // TODO: Currently security match current appdomain - - // Construct and initialize settings for a second AppDomain. - AppDomainSetup ads = new AppDomainSetup(); - ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; - ads.DisallowBindingRedirects = false; - ads.DisallowCodeDownload = true; - ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;) - ads.ShadowCopyFiles = "true"; // Enabled shadowing - ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; - - AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); - Console.WriteLine("Loading: " + - AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString()); - AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll")); - - // Return the new AppDomain - return AD; - } - - /// - /// Unload appdomains that are full and have only dead scripts - /// - private void UnloadAppDomains() - { - lock (freeLock) - { - // Go through all - foreach (AppDomainStructure ads in new ArrayList(appDomains)) - { - // Don't process current AppDomain - if (ads.CurrentAppDomain != currentAD.CurrentAppDomain) - { - // Not current AppDomain - // Is number of unloaded bigger or equal to number of loaded? - if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) - { - Console.WriteLine("Found empty AppDomain, unloading"); - // Remove from internal list - appDomains.Remove(ads); -#if DEBUG - long m = GC.GetTotalMemory(true); -#endif - // Unload - AppDomain.Unload(ads.CurrentAppDomain); -#if DEBUG - Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + - " bytes of memory"); -#endif - } - } - } // foreach - } // lock - } - - - public LSL_BaseClass LoadScript(string FileName) - { - // Find next available AppDomain to put it in - AppDomainStructure FreeAppDomain = GetFreeAppDomain(); - - Console.WriteLine("Loading into AppDomain: " + FileName); - LSL_BaseClass mbrt = - (LSL_BaseClass) - FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); - //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); - FreeAppDomain.ScriptsLoaded++; - - return mbrt; - } - - - /// - /// Increase "dead script" counter for an AppDomain - /// - /// - //[Obsolete("Needs fixing, needs a real purpose in life!!!")] - public void StopScript(AppDomain ad) - { - lock (freeLock) - { - Console.WriteLine("Stopping script in AppDomain"); - // Check if it is current AppDomain - if (currentAD.CurrentAppDomain == ad) - { - // Yes - increase - currentAD.ScriptsWaitingUnload++; - return; - } - - // Lopp through all AppDomains - foreach (AppDomainStructure ads in new ArrayList(appDomains)) - { - if (ads.CurrentAppDomain == ad) - { - // Found it - ads.ScriptsWaitingUnload++; - break; - } - } // foreach - } // lock - - UnloadAppDomains(); // Outsite lock, has its own GetLock - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + public class AppDomainManager : iScriptEngineFunctionModule + { + // + // This class does AppDomain handling and loading/unloading of scripts in it. + // It is instanced in "ScriptEngine" and controlled from "ScriptManager" + // + // 1. Create a new AppDomain if old one is full (or doesn't exist) + // 2. Load scripts into AppDomain + // 3. Unload scripts from AppDomain (stopping them and marking them as inactive) + // 4. Unload AppDomain completely when all scripts in it has stopped + // + + private int maxScriptsPerAppDomain = 1; + + /// + /// Internal list of all AppDomains + /// + private List appDomains = new List(); + + /// + /// Structure to keep track of data around AppDomain + /// + private class AppDomainStructure + { + /// + /// The AppDomain itself + /// + public AppDomain CurrentAppDomain; + + /// + /// Number of scripts loaded into AppDomain + /// + public int ScriptsLoaded; + + /// + /// Number of dead scripts + /// + public int ScriptsWaitingUnload; + } + + /// + /// Current AppDomain + /// + private AppDomainStructure currentAD; + + private object getLock = new object(); // Mutex + private object freeLock = new object(); // Mutex + + private ScriptEngine m_scriptEngine; + //public AppDomainManager(ScriptEngine scriptEngine) + public AppDomainManager(ScriptEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + ReadConfig(); + } + + public void ReadConfig() + { + maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1); + } + + /// + /// Find a free AppDomain, creating one if necessary + /// + /// Free AppDomain + private AppDomainStructure GetFreeAppDomain() + { + // Console.WriteLine("Finding free AppDomain"); + lock (getLock) + { + // Current full? + if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) + { + // Add it to AppDomains list and empty current + appDomains.Add(currentAD); + currentAD = null; + } + // No current + if (currentAD == null) + { + // Create a new current AppDomain + currentAD = new AppDomainStructure(); + currentAD.CurrentAppDomain = PrepareNewAppDomain(); + } + + // Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded); + return currentAD; + } + } + + private int AppDomainNameCount; + + /// + /// Create and prepare a new AppDomain for scripts + /// + /// The new AppDomain + private AppDomain PrepareNewAppDomain() + { + // Create and prepare a new AppDomain + AppDomainNameCount++; + // TODO: Currently security match current appdomain + + // Construct and initialize settings for a second AppDomain. + AppDomainSetup ads = new AppDomainSetup(); + ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; + ads.DisallowBindingRedirects = false; + ads.DisallowCodeDownload = true; + ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;) + ads.ShadowCopyFiles = "true"; // Enabled shadowing + ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; + + AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); + m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain Loading: " + + AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString()); + AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll")); + + // Return the new AppDomain + return AD; + } + + /// + /// Unload appdomains that are full and have only dead scripts + /// + private void UnloadAppDomains() + { + lock (freeLock) + { + // Go through all + foreach (AppDomainStructure ads in new ArrayList(appDomains)) + { + // Don't process current AppDomain + if (ads.CurrentAppDomain != currentAD.CurrentAppDomain) + { + // Not current AppDomain + // Is number of unloaded bigger or equal to number of loaded? + if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) + { + // Remove from internal list + appDomains.Remove(ads); +#if DEBUG + Console.WriteLine("Found empty AppDomain, unloading"); + long m = GC.GetTotalMemory(true); +#endif + // Unload + AppDomain.Unload(ads.CurrentAppDomain); +#if DEBUG + m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory"); +#endif + } + } + } + } + } + + public IScript LoadScript(string FileName) + { + // Find next available AppDomain to put it in + AppDomainStructure FreeAppDomain = GetFreeAppDomain(); + +#if DEBUG + m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Loading into AppDomain: " + FileName); +#endif + IScript mbrt = + (IScript) + FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); + //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); + FreeAppDomain.ScriptsLoaded++; + + return mbrt; + } + + + /// + /// Increase "dead script" counter for an AppDomain + /// + /// + //[Obsolete("Needs fixing, needs a real purpose in life!!!")] + public void StopScript(AppDomain ad) + { + lock (freeLock) + { +#if DEBUG + m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Stopping script in AppDomain"); +#endif + // Check if it is current AppDomain + if (currentAD.CurrentAppDomain == ad) + { + // Yes - increase + currentAD.ScriptsWaitingUnload++; + return; + } + + // Lopp through all AppDomains + foreach (AppDomainStructure ads in new ArrayList(appDomains)) + { + if (ads.CurrentAppDomain == ad) + { + // Found it + ads.ScriptsWaitingUnload++; + break; + } + } + } + + UnloadAppDomains(); // Outsite lock, has its own GetLock + } + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs new file mode 100644 index 0000000000..33c651102a --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs @@ -0,0 +1,408 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc. + /// + public class AsyncLSLCommandManager : iScriptEngineFunctionModule + { + private static Thread cmdHandlerThread; + private static int cmdHandlerThreadCycleSleepms; + + private ScriptEngine m_ScriptEngine; + + public AsyncLSLCommandManager(ScriptEngine _ScriptEngine) + { + m_ScriptEngine = _ScriptEngine; + ReadConfig(); + + StartThread(); + } + + private void StartThread() + { + if (cmdHandlerThread == null) + { + // Start the thread that will be doing the work + cmdHandlerThread = new Thread(CmdHandlerThreadLoop); + cmdHandlerThread.Name = "AsyncLSLCmdHandlerThread"; + cmdHandlerThread.Priority = ThreadPriority.BelowNormal; + cmdHandlerThread.IsBackground = true; + cmdHandlerThread.Start(); + OpenSim.Framework.ThreadTracker.Add(cmdHandlerThread); + } + } + + public void ReadConfig() + { + cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 100); + } + + ~AsyncLSLCommandManager() + { + // Shut down thread + try + { + if (cmdHandlerThread != null) + { + if (cmdHandlerThread.IsAlive == true) + { + cmdHandlerThread.Abort(); + //cmdHandlerThread.Join(); + } + } + } + catch + { + } + } + + private static void CmdHandlerThreadLoop() + { + while (true) + { + try + { + while (true) + { + Thread.Sleep(cmdHandlerThreadCycleSleepms); + //lock (ScriptEngine.ScriptEngines) + //{ + foreach (ScriptEngine se in new ArrayList(ScriptEngine.ScriptEngines)) + { + se.m_ASYNCLSLCommandManager.DoOneCmdHandlerPass(); + } + //} + // Sleep before next cycle + //Thread.Sleep(cmdHandlerThreadCycleSleepms); + } + } + catch + { + } + } + } + + internal void DoOneCmdHandlerPass() + { + // Check timers + CheckTimerEvents(); + // Check HttpRequests + CheckHttpRequests(); + // Check XMLRPCRequests + CheckXMLRPCRequests(); + // Check Listeners + CheckListeners(); + } + + /// + /// Remove a specific script (and all its pending commands) + /// + /// + /// + public void RemoveScript(uint localID, LLUUID itemID) + { + // Remove a specific script + + // Remove from: Timers + UnSetTimerEvents(localID, itemID); + // Remove from: HttpRequest + IHttpRequests iHttpReq = + m_ScriptEngine.World.RequestModuleInterface(); + iHttpReq.StopHttpRequest(localID, itemID); + + IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface(); + comms.DeleteListener(itemID); + + IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpc.DeleteChannels(itemID); + + xmlrpc.CancelSRDRequests(itemID); + + } + + #region TIMER + + // + // TIMER + // + private class TimerClass + { + public uint localID; + public LLUUID itemID; + //public double interval; + public long interval; + //public DateTime next; + public long next; + } + + private List Timers = new List(); + private object TimerListLock = new object(); + + public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec) + { + Console.WriteLine("SetTimerEvent"); + + // Always remove first, in case this is a re-set + UnSetTimerEvents(m_localID, m_itemID); + if (sec == 0) // Disabling timer + return; + + // Add to timer + TimerClass ts = new TimerClass(); + ts.localID = m_localID; + ts.itemID = m_itemID; + ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait + // 2193386136332921 ticks + // 219338613 seconds + + //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + ts.next = DateTime.Now.Ticks + ts.interval; + lock (TimerListLock) + { + Timers.Add(ts); + } + } + + public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID) + { + // Remove from timer + lock (TimerListLock) + { + foreach (TimerClass ts in new ArrayList(Timers)) + { + if (ts.localID == m_localID && ts.itemID == m_itemID) + Timers.Remove(ts); + } + } + + // Old method: Create new list + //List NewTimers = new List(); + //foreach (TimerClass ts in Timers) + //{ + // if (ts.localID != m_localID && ts.itemID != m_itemID) + // { + // NewTimers.Add(ts); + // } + //} + //Timers.Clear(); + //Timers = NewTimers; + //} + } + + public void CheckTimerEvents() + { + // Nothing to do here? + if (Timers.Count == 0) + return; + + lock (TimerListLock) + { + // Go through all timers + foreach (TimerClass ts in Timers) + { + // Time has passed? + if (ts.next < DateTime.Now.Ticks) + { +// Console.WriteLine("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); + // Add it to queue + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull, + null); + // set next interval + + //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + ts.next = DateTime.Now.Ticks + ts.interval; + } + } + } + } + + #endregion + + #region HTTP REQUEST + + public void CheckHttpRequests() + { + if (m_ScriptEngine.World == null) + return; + + IHttpRequests iHttpReq = + m_ScriptEngine.World.RequestModuleInterface(); + + HttpRequestClass httpInfo = null; + + if (iHttpReq != null) + httpInfo = iHttpReq.GetNextCompletedRequest(); + + while (httpInfo != null) + { + //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status); + + // Deliver data to prim's remote_data handler + // + // TODO: Returning null for metadata, since the lsl function + // only returns the byte for HTTP_BODY_TRUNCATED, which is not + // implemented here yet anyway. Should be fixed if/when maxsize + // is supported + + if (m_ScriptEngine.m_ScriptManager.GetScript(httpInfo.localID, httpInfo.itemID) != null) + { + iHttpReq.RemoveCompletedRequest(httpInfo.reqID); + object[] resobj = new object[] + { + httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body + }; + + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj + ); + + } + + httpInfo = iHttpReq.GetNextCompletedRequest(); + } + } + + #endregion + + #region Check llRemoteData channels + + public void CheckXMLRPCRequests() + { + if (m_ScriptEngine.World == null) + return; + + IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface(); + + if (xmlrpc != null) + { + RPCRequestInfo rInfo = xmlrpc.GetNextCompletedRequest(); + + while (rInfo != null) + { + if (m_ScriptEngine.m_ScriptManager.GetScript(rInfo.GetLocalID(), rInfo.GetItemID()) != null) + { + xmlrpc.RemoveCompletedRequest(rInfo.GetMessageID()); + + //Deliver data to prim's remote_data handler + object[] resobj = new object[] + { + 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty, + rInfo.GetIntValue(), + rInfo.GetStrVal() + }; + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj + ); + } + + rInfo = xmlrpc.GetNextCompletedRequest(); + } + + SendRemoteDataRequest srdInfo = xmlrpc.GetNextCompletedSRDRequest(); + + while (srdInfo != null) + { + if (m_ScriptEngine.m_ScriptManager.GetScript(srdInfo.m_localID, srdInfo.m_itemID) != null) + { + xmlrpc.RemoveCompletedSRDRequest(srdInfo.GetReqID()); + + //Deliver data to prim's remote_data handler + object[] resobj = new object[] + { + 3, srdInfo.channel.ToString(), srdInfo.GetReqID().ToString(), String.Empty, + srdInfo.idata, + srdInfo.sdata + }; + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + srdInfo.m_localID, srdInfo.m_itemID, "remote_data", EventQueueManager.llDetectNull, resobj + ); + } + + srdInfo = xmlrpc.GetNextCompletedSRDRequest(); + } + } + } + + #endregion + + #region Check llListeners + + public void CheckListeners() + { + if (m_ScriptEngine.World == null) + return; + IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface(); + + if (comms != null) + { + while (comms.HasMessages()) + { + if (m_ScriptEngine.m_ScriptManager.GetScript( + comms.PeekNextMessageLocalID(), comms.PeekNextMessageItemID()) != null) + { + ListenerInfo lInfo = comms.GetNextMessage(); + + //Deliver data to prim's listen handler + object[] resobj = new object[] + { + lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() + }; + + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj + ); + } + } + } + } + + #endregion + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs similarity index 79% rename from OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs rename to OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs index bd7f1a90f6..82789b264f 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs @@ -1,57 +1,57 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -namespace OpenSim.Region.ScriptEngine.DotNetEngine -{ - public static class Common - { - public static bool debug = true; - public static ScriptEngine mySE; - - // This class just contains some static log stuff used for debugging. - - //public delegate void SendToDebugEventDelegate(string Message); - //public delegate void SendToLogEventDelegate(string Message); - //static public event SendToDebugEventDelegate SendToDebugEvent; - //static public event SendToLogEventDelegate SendToLogEvent; - - public static void SendToDebug(string Message) - { - //if (Debug == true) - mySE.Log.Verbose("ScriptEngine", "Debug: " + Message); - //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); - } - - public static void SendToLog(string Message) - { - //if (Debug == true) - mySE.Log.Verbose("ScriptEngine", "LOG: " + Message); - //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + public static class Common + { + public static bool debug = true; + public static ScriptEngine mySE; + + // This class just contains some static log stuff used for debugging. + + //public delegate void SendToDebugEventDelegate(string message); + //public delegate void SendToLogEventDelegate(string message); + //static public event SendToDebugEventDelegate SendToDebugEvent; + //static public event SendToLogEventDelegate SendToLogEvent; + + public static void SendToDebug(string message) + { + //if (Debug == true) + mySE.Log.Info("[" + mySE.ScriptEngineName + "]: Debug: " + message); + //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message); + } + + public static void SendToLog(string message) + { + //if (Debug == true) + mySE.Log.Info("[" + mySE.ScriptEngineName + "]: LOG: " + message); + //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs similarity index 51% rename from OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs rename to OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs index 75e5d91ed0..b091e04ed1 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs @@ -1,237 +1,288 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -using System; -using libsecondlife; -using OpenSim.Framework; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine -{ - /// - /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. - /// - [Serializable] - public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents - { - - // - // Class is instanced in "ScriptEngine" and Uses "EventQueueManager" that is also instanced in "ScriptEngine". - // This class needs a bit of explaining: - // - // This class it the link between an event inside OpenSim and the corresponding event in a user script being executed. - // - // For example when an user touches an object then the "myScriptEngine.World.EventManager.OnObjectGrab" event is fired inside OpenSim. - // We hook up to this event and queue a touch_start in EventQueueManager with the proper LSL parameters. - // It will then be delivered to the script by EventQueueManager. - // - // You can check debug C# dump of an LSL script if you need to verify what exact parameters are needed. - // - - - private ScriptEngine myScriptEngine; - //public IScriptHost TEMP_OBJECT_ID; - public EventManager(ScriptEngine _ScriptEngine) - { - myScriptEngine = _ScriptEngine; - // TODO: HOOK EVENTS UP TO SERVER! - //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventManager Start"); - // TODO: ADD SERVER HOOK TO LOAD A SCRIPT THROUGH myScriptEngine.ScriptManager - - // Hook up a test event to our test form - myScriptEngine.Log.Verbose("ScriptEngine", "Hooking up to server events"); - myScriptEngine.World.EventManager.OnObjectGrab += touch_start; - myScriptEngine.World.EventManager.OnRezScript += OnRezScript; - myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; - } - - public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) - { - // Add to queue for all scripts in ObjectID object - //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventManager Event: touch_start"); - //Console.WriteLine("touch_start localID: " + localID); - OpenSim.Region.Environment.Scenes.SceneObjectPart sop = this.myScriptEngine.World.GetSceneObjectPart(localID); - sop.TouchedBy = remoteClient.AgentId; - myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] {(int) 1}); - } - - public void OnRezScript(uint localID, LLUUID itemID, string script) - { - //myScriptEngine.myScriptManager.StartScript( - // Path.Combine("ScriptEngines", "Default.lsl"), - // new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost() - //); - Console.WriteLine("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " + - script.Length); - myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script); - } - - public void OnRemoveScript(uint localID, LLUUID itemID) - { - //myScriptEngine.myScriptManager.StartScript( - // Path.Combine("ScriptEngines", "Default.lsl"), - // new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost() - //); - Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString()); - myScriptEngine.m_ScriptManager.StopScript( - localID, - itemID - ); - } - - // TODO: Replace placeholders below - // These needs to be hooked up to OpenSim during init of this class - // then queued in EventQueueManager. - // When queued in EventQueueManager they need to be LSL compatible (name and params) - - //public void state_entry() { } // - public void state_exit(uint localID, LLUUID itemID) - { - } - - //public void touch_start(uint localID, LLUUID itemID) { } - public void touch(uint localID, LLUUID itemID) - { - } - - public void touch_end(uint localID, LLUUID itemID) - { - } - - public void collision_start(uint localID, LLUUID itemID) - { - } - - public void collision(uint localID, LLUUID itemID) - { - } - - public void collision_end(uint localID, LLUUID itemID) - { - } - - public void land_collision_start(uint localID, LLUUID itemID) - { - } - - public void land_collision(uint localID, LLUUID itemID) - { - } - - public void land_collision_end(uint localID, LLUUID itemID) - { - } - - public void timer(uint localID, LLUUID itemID) - { - } - - public void listen(uint localID, LLUUID itemID) - { - } - - public void on_rez(uint localID, LLUUID itemID) - { - } - - public void sensor(uint localID, LLUUID itemID) - { - } - - public void no_sensor(uint localID, LLUUID itemID) - { - } - - public void control(uint localID, LLUUID itemID) - { - } - - public void money(uint localID, LLUUID itemID) - { - } - - public void email(uint localID, LLUUID itemID) - { - } - - public void at_target(uint localID, LLUUID itemID) - { - } - - public void not_at_target(uint localID, LLUUID itemID) - { - } - - public void at_rot_target(uint localID, LLUUID itemID) - { - } - - public void not_at_rot_target(uint localID, LLUUID itemID) - { - } - - public void run_time_permissions(uint localID, LLUUID itemID) - { - } - - public void changed(uint localID, LLUUID itemID) - { - } - - public void attach(uint localID, LLUUID itemID) - { - } - - public void dataserver(uint localID, LLUUID itemID) - { - } - - public void link_message(uint localID, LLUUID itemID) - { - } - - public void moving_start(uint localID, LLUUID itemID) - { - } - - public void moving_end(uint localID, LLUUID itemID) - { - } - - public void object_rez(uint localID, LLUUID itemID) - { - } - - public void remote_data(uint localID, LLUUID itemID) - { - } - - public void http_response(uint localID, LLUUID itemID) - { - } - } +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + + +using System; +using libsecondlife; +using OpenSim.Framework; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. + /// + [Serializable] + public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents, iScriptEngineFunctionModule + { + // + // Class is instanced in "ScriptEngine" and Uses "EventQueueManager" that is also instanced in "ScriptEngine". + // This class needs a bit of explaining: + // + // This class it the link between an event inside OpenSim and the corresponding event in a user script being executed. + // + // For example when an user touches an object then the "myScriptEngine.World.EventManager.OnObjectGrab" event is fired inside OpenSim. + // We hook up to this event and queue a touch_start in EventQueueManager with the proper LSL parameters. + // It will then be delivered to the script by EventQueueManager. + // + // You can check debug C# dump of an LSL script if you need to verify what exact parameters are needed. + // + + + private ScriptEngine myScriptEngine; + //public IScriptHost TEMP_OBJECT_ID; + public EventManager(ScriptEngine _ScriptEngine, bool performHookUp) + { + myScriptEngine = _ScriptEngine; + ReadConfig(); + + // Hook up to events from OpenSim + // We may not want to do it because someone is controlling us and will deliver events to us + if (performHookUp) + { + myScriptEngine.Log.Info("[" + myScriptEngine.ScriptEngineName + "]: Hooking up to server events"); + myScriptEngine.World.EventManager.OnObjectGrab += touch_start; + myScriptEngine.World.EventManager.OnRezScript += OnRezScript; + myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; + myScriptEngine.World.EventManager.OnScriptChangedEvent += changed; + // TODO: HOOK ALL EVENTS UP TO SERVER! + } + } + + public void ReadConfig() + { + } + + public void changed(uint localID, uint change) + { + // Add to queue for all scripts in localID, Object pass change. + myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "changed", EventQueueManager.llDetectNull, new object[] { (int)change }); + } + + public void state_entry(uint localID) + { + // Add to queue for all scripts in ObjectID object + myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "state_entry", EventQueueManager.llDetectNull, new object[] { }); + } + + public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", EventQueueManager.llDetectNull, new object[] { (int)1 }); + } + + public void OnRezScript(uint localID, LLUUID itemID, string script) + { + Console.WriteLine("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " + + script.Length); + myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script); + } + + public void OnRemoveScript(uint localID, LLUUID itemID) + { + Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString()); + myScriptEngine.m_ScriptManager.StopScript( + localID, + itemID + ); + } + + // TODO: Replace placeholders below + // NOTE! THE PARAMETERS FOR THESE FUNCTIONS ARE NOT CORRECT! + // These needs to be hooked up to OpenSim during init of this class + // then queued in EventQueueManager. + // When queued in EventQueueManager they need to be LSL compatible (name and params) + + public void state_exit(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_exit", EventQueueManager.llDetectNull); + } + + public void touch(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch", EventQueueManager.llDetectNull); + } + + public void touch_end(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch_end", EventQueueManager.llDetectNull); + } + + public void collision_start(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_start", EventQueueManager.llDetectNull); + } + + public void collision(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision", EventQueueManager.llDetectNull); + } + + public void collision_end(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_end", EventQueueManager.llDetectNull); + } + + public void land_collision_start(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_start", EventQueueManager.llDetectNull); + } + + public void land_collision(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision", EventQueueManager.llDetectNull); + } + + public void land_collision_end(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_end", EventQueueManager.llDetectNull); + } + + // Handled by long commands + public void timer(uint localID, LLUUID itemID) + { + //myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, String.Empty); + } + + public void listen(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "listen", EventQueueManager.llDetectNull); + } + + public void on_rez(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "on_rez", EventQueueManager.llDetectNull); + } + + public void sensor(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "sensor", EventQueueManager.llDetectNull); + } + + public void no_sensor(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "no_sensor", EventQueueManager.llDetectNull); + } + + public void control(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "control", EventQueueManager.llDetectNull); + } + + public void money(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "money", EventQueueManager.llDetectNull); + } + + public void email(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "email", EventQueueManager.llDetectNull); + } + + public void at_target(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_target", EventQueueManager.llDetectNull); + } + + public void not_at_target(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_target", EventQueueManager.llDetectNull); + } + + public void at_rot_target(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_rot_target", EventQueueManager.llDetectNull); + } + + public void not_at_rot_target(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_rot_target", EventQueueManager.llDetectNull); + } + + public void run_time_permissions(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "run_time_permissions", EventQueueManager.llDetectNull); + } + + public void changed(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "changed", EventQueueManager.llDetectNull); + } + + public void attach(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "attach", EventQueueManager.llDetectNull); + } + + public void dataserver(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "dataserver", EventQueueManager.llDetectNull); + } + + public void link_message(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "link_message", EventQueueManager.llDetectNull); + } + + public void moving_start(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_start", EventQueueManager.llDetectNull); + } + + public void moving_end(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_end", EventQueueManager.llDetectNull); + } + + public void object_rez(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "object_rez", EventQueueManager.llDetectNull); + } + + public void remote_data(uint localID, LLUUID itemID) + { + myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "remote_data", EventQueueManager.llDetectNull); + } + + // Handled by long commands + public void http_response(uint localID, LLUUID itemID) + { + // myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "http_response", EventQueueManager.llDetectNull); + } + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + + } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs new file mode 100644 index 0000000000..825686b6ea --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs @@ -0,0 +1,437 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes.Scripting; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// EventQueueManager handles event queues + /// Events are queued and executed in separate thread + /// + [Serializable] + public class EventQueueManager : iScriptEngineFunctionModule + { + // + // Class is instanced in "ScriptEngine" and used by "EventManager" which is also instanced in "ScriptEngine". + // + // Class purpose is to queue and execute functions that are received by "EventManager": + // - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution. + // - allowing us to prioritize and control execution of script functions. + // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety. + // + // 1. Hold an execution queue for scripts + // 2. Use threads to process queue, each thread executes one script function on each pass. + // 3. Catch any script error and process it + // + // + // Notes: + // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts. + // Not noticeable unless server is under high load. + // + + public ScriptEngine m_ScriptEngine; + + /// + /// List of threads (classes) processing event queue + /// Note that this may or may not be a reference to a static object depending on PrivateRegionThreads config setting. + /// + internal static List eventQueueThreads = new List(); // Thread pool that we work on + /// + /// Locking access to eventQueueThreads AND staticGlobalEventQueueThreads. + /// +// private object eventQueueThreadsLock = new object(); + // Static objects for referencing the objects above if we don't have private threads: + //internal static List staticEventQueueThreads; // A static reference used if we don't use private threads +// internal static object staticEventQueueThreadsLock; // Statick lock object reference for same reason + + /// + /// Global static list of all threads (classes) processing event queue -- used by max enforcment thread + /// + //private List staticGlobalEventQueueThreads = new List(); + + /// + /// Used internally to specify how many threads should exit gracefully + /// + public static int ThreadsToExit; + public static object ThreadsToExitLock = new object(); + + + //public object queueLock = new object(); // Mutex lock object + + /// + /// How many threads to process queue with + /// + internal static int numberOfThreads; + + internal static int EventExecutionMaxQueueSize; + + /// + /// Maximum time one function can use for execution before we perform a thread kill. + /// + private static int maxFunctionExecutionTimems + { + get { return (int)(maxFunctionExecutionTimens / 10000); } + set { maxFunctionExecutionTimens = value * 10000; } + } + + /// + /// Contains nanoseconds version of maxFunctionExecutionTimems so that it matches time calculations better (performance reasons). + /// WARNING! ONLY UPDATE maxFunctionExecutionTimems, NEVER THIS DIRECTLY. + /// + public static long maxFunctionExecutionTimens; + /// + /// Enforce max execution time + /// + public static bool EnforceMaxExecutionTime; + /// + /// Kill script (unload) when it exceeds execution time + /// + private static bool KillScriptOnMaxFunctionExecutionTime; + + /// + /// List of localID locks for mutex processing of script events + /// + private List objectLocks = new List(); + private object tryLockLock = new object(); // Mutex lock object + + /// + /// Queue containing events waiting to be executed + /// + public Queue eventQueue = new Queue(); + + #region " Queue structures " + /// + /// Queue item structure + /// + public struct QueueItemStruct + { + public uint localID; + public LLUUID itemID; + public string functionName; + public Queue_llDetectParams_Struct llDetectParams; + public object[] param; + } + + /// + /// Shared empty llDetectNull + /// + public readonly static Queue_llDetectParams_Struct llDetectNull = new Queue_llDetectParams_Struct(); + + /// + /// Structure to hold data for llDetect* commands + /// + [Serializable] + public struct Queue_llDetectParams_Struct + { + // More or less just a placeholder for the actual moving of additional data + // should be fixed to something better :) + public LSL_Types.key[] _key; + public LSL_Types.Quaternion[] _Quaternion; + public LSL_Types.Vector3[] _Vector3; + public bool[] _bool; + public int[] _int; + public string[] _string; + } + #endregion + + #region " Initialization / Startup " + public EventQueueManager(ScriptEngine _ScriptEngine) + { + m_ScriptEngine = _ScriptEngine; + + ReadConfig(); + AdjustNumberOfScriptThreads(); + } + + public void ReadConfig() + { + // Refresh config + numberOfThreads = m_ScriptEngine.ScriptConfigSource.GetInt("NumberOfScriptThreads", 2); + maxFunctionExecutionTimems = m_ScriptEngine.ScriptConfigSource.GetInt("MaxEventExecutionTimeMs", 5000); + EnforceMaxExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("EnforceMaxEventExecutionTime", false); + KillScriptOnMaxFunctionExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("DeactivateScriptOnTimeout", false); + EventExecutionMaxQueueSize = m_ScriptEngine.ScriptConfigSource.GetInt("EventExecutionMaxQueueSize", 300); + + // Now refresh config in all threads + lock (eventQueueThreads) + { + foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads) + { + EventQueueThread.ReadConfig(); + } + } + } + + #endregion + + #region " Shutdown all threads " + ~EventQueueManager() + { + Stop(); + } + + private void Stop() + { + if (eventQueueThreads != null) + { + // Kill worker threads + lock (eventQueueThreads) + { + foreach (EventQueueThreadClass EventQueueThread in new ArrayList(eventQueueThreads)) + { + AbortThreadClass(EventQueueThread); + } + //eventQueueThreads.Clear(); + //staticGlobalEventQueueThreads.Clear(); + } + } + + // Remove all entries from our event queue + lock (eventQueue) + { + eventQueue.Clear(); + } + } + + #endregion + + #region " Start / stop script execution threads (ThreadClasses) " + private void StartNewThreadClass() + { + EventQueueThreadClass eqtc = new EventQueueThreadClass(); + eventQueueThreads.Add(eqtc); + m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Started new script execution thread. Current thread count: " + eventQueueThreads.Count); + } + + private void AbortThreadClass(EventQueueThreadClass threadClass) + { + if (eventQueueThreads.Contains(threadClass)) + eventQueueThreads.Remove(threadClass); + + try + { + threadClass.Stop(); + } + catch (Exception ex) + { + //m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + ":EventQueueManager]: If you see this, could you please report it to Tedd:"); + //m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + ":EventQueueManager]: Script thread execution timeout kill ended in exception: " + ex.ToString()); + } + //m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Killed script execution thread. Remaining thread count: " + eventQueueThreads.Count); + } + #endregion + + #region " Mutex locks for queue access " + /// + /// Try to get a mutex lock on localID + /// + /// + /// + public bool TryLock(uint localID) + { + lock (tryLockLock) + { + if (objectLocks.Contains(localID) == true) + { + return false; + } + else + { + objectLocks.Add(localID); + return true; + } + } + } + + /// + /// Release mutex lock on localID + /// + /// + public void ReleaseLock(uint localID) + { + lock (tryLockLock) + { + if (objectLocks.Contains(localID) == true) + { + objectLocks.Remove(localID); + } + } + } + #endregion + + #region " Add events to execution queue " + /// + /// Add event to event execution queue + /// + /// Region object ID + /// Name of the function, will be state + "_event_" + FunctionName + /// Array of parameters to match event mask + public void AddToObjectQueue(uint localID, string FunctionName, Queue_llDetectParams_Struct qParams, params object[] param) + { + // Determine all scripts in Object and add to their queue + //myScriptEngine.log.Info("[" + ScriptEngineName + "]: EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName); + + // Do we have any scripts in this object at all? If not, return + if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false) + { + //Console.WriteLine("Event \String.Empty + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID."); + return; + } + + Dictionary.KeyCollection scriptKeys = + m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID); + + foreach (LLUUID itemID in scriptKeys) + { + // Add to each script in that object + // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? + AddToScriptQueue(localID, itemID, FunctionName, qParams, param); + } + } + + /// + /// Add event to event execution queue + /// + /// Region object ID + /// Region script ID + /// Name of the function, will be state + "_event_" + FunctionName + /// Array of parameters to match event mask + public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, Queue_llDetectParams_Struct qParams, params object[] param) + { + lock (eventQueue) + { + if (eventQueue.Count >= EventExecutionMaxQueueSize) + { + m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: ERROR: Event execution queue item count is at " + eventQueue.Count + ". Config variable \"EventExecutionMaxQueueSize\" is set to " + EventExecutionMaxQueueSize + ", so ignoring new event."); + m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: Event ignored: localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); + return; + } + + // Create a structure and add data + QueueItemStruct QIS = new QueueItemStruct(); + QIS.localID = localID; + QIS.itemID = itemID; + QIS.functionName = FunctionName; + QIS.llDetectParams = qParams; + QIS.param = param; + + // Add it to queue + eventQueue.Enqueue(QIS); + } + } + #endregion + + #region " Maintenance thread " + + /// + /// Adjust number of script thread classes. It can start new, but if it needs to stop it will just set number of threads in "ThreadsToExit" and threads will have to exit themselves. + /// Called from MaintenanceThread + /// + public void AdjustNumberOfScriptThreads() + { + // Is there anything here for us to do? + if (eventQueueThreads.Count == numberOfThreads) + return; + + lock (eventQueueThreads) + { + int diff = numberOfThreads - eventQueueThreads.Count; + // Positive number: Start + // Negative number: too many are running + if (diff > 0) + { + // We need to add more threads + for (int ThreadCount = eventQueueThreads.Count; ThreadCount < numberOfThreads; ThreadCount++) + { + StartNewThreadClass(); + } + } + if (diff < 0) + { + // We need to kill some threads + lock (ThreadsToExitLock) + { + ThreadsToExit = Math.Abs(diff); + } + } + } + } + + /// + /// Check if any thread class has been executing an event too long + /// + public void CheckScriptMaxExecTime() + { + // Iterate through all ScriptThreadClasses and check how long their current function has been executing + lock (eventQueueThreads) + { + foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads) + { + // Is thread currently executing anything? + if (EventQueueThread.InExecution) + { + // Has execution time expired? + if (DateTime.Now.Ticks - EventQueueThread.LastExecutionStarted > + maxFunctionExecutionTimens) + { + // Yes! We need to kill this thread! + + // Set flag if script should be removed or not + EventQueueThread.KillCurrentScript = KillScriptOnMaxFunctionExecutionTime; + + // Abort this thread + AbortThreadClass(EventQueueThread); + + // We do not need to start another, MaintenenceThread will do that for us + //StartNewThreadClass(); + } + } + } + } + } + #endregion + + ///// + ///// If set to true then threads and stuff should try to make a graceful exit + ///// + //public bool PleaseShutdown + //{ + // get { return _PleaseShutdown; } + // set { _PleaseShutdown = value; } + //} + //private bool _PleaseShutdown = false; + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs new file mode 100644 index 0000000000..3a237da3d7 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs @@ -0,0 +1,364 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes.Scripting; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class + /// + public class EventQueueThreadClass : iScriptEngineFunctionModule + { + /// + /// How many ms to sleep if queue is empty + /// + private static int nothingToDoSleepms;// = 50; + private static ThreadPriority MyThreadPriority; + + public long LastExecutionStarted; + public bool InExecution = false; + public bool KillCurrentScript = false; + + //private EventQueueManager eventQueueManager; + public Thread EventQueueThread; + private static int ThreadCount = 0; + + private string ScriptEngineName = "ScriptEngine.Common"; + + public EventQueueThreadClass()//EventQueueManager eqm + { + //eventQueueManager = eqm; + ReadConfig(); + Start(); + } + + ~EventQueueThreadClass() + { + Stop(); + } + + public void ReadConfig() + { + lock (ScriptEngine.ScriptEngines) + { + foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines) + { + ScriptEngineName = m_ScriptEngine.ScriptEngineName; + nothingToDoSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50); + + // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually + string pri = m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal"); + switch (pri.ToLower()) + { + case "lowest": + MyThreadPriority = ThreadPriority.Lowest; + break; + case "belownormal": + MyThreadPriority = ThreadPriority.BelowNormal; + break; + case "normal": + MyThreadPriority = ThreadPriority.Normal; + break; + case "abovenormal": + MyThreadPriority = ThreadPriority.AboveNormal; + break; + case "highest": + MyThreadPriority = ThreadPriority.Highest; + break; + default: + MyThreadPriority = ThreadPriority.BelowNormal; // Default + m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri + + "\" in config file. Defaulting to \"BelowNormal\"."); + break; + } + } + } + // Now set that priority + if (EventQueueThread != null) + if (EventQueueThread.IsAlive) + EventQueueThread.Priority = MyThreadPriority; + } + + /// + /// Start thread + /// + private void Start() + { + EventQueueThread = new Thread(EventQueueThreadLoop); + EventQueueThread.IsBackground = true; + + EventQueueThread.Priority = MyThreadPriority; + EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; + EventQueueThread.Start(); + OpenSim.Framework.ThreadTracker.Add(EventQueueThread); + + // Look at this... Don't you wish everyone did that solid coding everywhere? :P + if (ThreadCount == int.MaxValue) + ThreadCount = 0; + ThreadCount++; + } + + public void Stop() + { + //PleaseShutdown = true; // Set shutdown flag + //Thread.Sleep(100); // Wait a bit + if (EventQueueThread != null && EventQueueThread.IsAlive == true) + { + try + { + EventQueueThread.Abort(); // Send abort + //EventQueueThread.Join(); // Wait for it + } + catch (Exception) + { + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Exception killing worker thread: " + e.ToString()); + } + } + } + + private EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct(); + private ScriptEngine lastScriptEngine; + /// + /// Queue processing thread loop + /// + private void EventQueueThreadLoop() + { + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread spawned"); + try + { + while (true) + { + try + { + while (true) + { + DoProcessQueue(); + } + } + catch (ThreadAbortException tae) + { + if (lastScriptEngine != null) + lastScriptEngine.Log.Info("[" + ScriptEngineName + "]: ThreadAbortException while executing function."); + } + catch (Exception e) + { + if (lastScriptEngine != null) + lastScriptEngine.Log.Error("[" + ScriptEngineName + "]: Exception in EventQueueThreadLoop: " + e.ToString()); + } + } + } + catch (ThreadAbortException) + { + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread killed: " + tae.Message); + } + } + + public void DoProcessQueue() + { + //lock (ScriptEngine.ScriptEngines) + //{ + foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines)) + { + lastScriptEngine = m_ScriptEngine; + // Every now and then check if we should shut down + //if (PleaseShutdown || EventQueueManager.ThreadsToExit > 0) + //{ + // // Someone should shut down, lets get exclusive lock + // lock (EventQueueManager.ThreadsToExitLock) + // { + // // Lets re-check in case someone grabbed it + // if (EventQueueManager.ThreadsToExit > 0) + // { + // // Its crowded here so we'll shut down + // EventQueueManager.ThreadsToExit--; + // Stop(); + // return; + // } + // else + // { + // // We have been asked to shut down + // Stop(); + // return; + // } + // } + //} + + //try + // { + EventQueueManager.QueueItemStruct QIS = BlankQIS; + bool GotItem = false; + + //if (PleaseShutdown) + // return; + + if (m_ScriptEngine.m_EventQueueManager == null || m_ScriptEngine.m_EventQueueManager.eventQueue == null) + continue; + + if (m_ScriptEngine.m_EventQueueManager.eventQueue.Count == 0) + { + // Nothing to do? Sleep a bit waiting for something to do + Thread.Sleep(nothingToDoSleepms); + } + else + { + // Something in queue, process + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); + + // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD + lock (m_ScriptEngine.m_EventQueueManager.eventQueue) + { + GotItem = false; + for (int qc = 0; qc < m_ScriptEngine.m_EventQueueManager.eventQueue.Count; qc++) + { + // Get queue item + QIS = m_ScriptEngine.m_EventQueueManager.eventQueue.Dequeue(); + + // Check if object is being processed by someone else + if (m_ScriptEngine.m_EventQueueManager.TryLock(QIS.localID) == false) + { + // Object is already being processed, requeue it + m_ScriptEngine.m_EventQueueManager.eventQueue.Enqueue(QIS); + } + else + { + // We have lock on an object and can process it + GotItem = true; + break; + } + } + } + + if (GotItem == true) + { + // Execute function + try + { + ///cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined +#if DEBUG + //eventQueueManager.m_ScriptEngine.Log.Debug("[" + ScriptEngineName + "]: " + + // "Executing event:\r\n" + // + "QIS.localID: " + QIS.localID + // + ", QIS.itemID: " + QIS.itemID + // + ", QIS.functionName: " + + // QIS.functionName); +#endif + LastExecutionStarted = DateTime.Now.Ticks; + KillCurrentScript = false; + InExecution = true; + m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, + QIS.itemID, + QIS.functionName, + QIS.llDetectParams, + QIS.param); + InExecution = false; + } + catch (Exception e) + { + InExecution = false; + // DISPLAY ERROR INWORLD + string text = "Error executing script function \"" + QIS.functionName + + "\":\r\n"; + if (e.InnerException != null) + { + // Send inner exception + text += e.InnerException.Message.ToString(); + } + else + { + text += "\r\n"; + // Send normal + text += e.Message.ToString(); + } + if (KillCurrentScript) + text += "\r\nScript will be deactivated!"; + + try + { + if (text.Length > 1500) + text = text.Substring(0, 1500); + IScriptHost m_host = + m_ScriptEngine.World.GetSceneObjectPart(QIS.localID); + //if (m_host != null) + //{ + m_ScriptEngine.World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Say, 0, + m_host.AbsolutePosition, + m_host.Name, m_host.UUID); + } + catch + { + //} + //else + //{ + // T oconsole + m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + + "]: " + + "Unable to send text in-world:\r\n" + + text); + } + finally + { + // So we are done sending message in-world + if (KillCurrentScript) + { + m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript( + QIS.localID, QIS.itemID); + } + } + } + finally + { + InExecution = false; + m_ScriptEngine.m_EventQueueManager.ReleaseLock(QIS.localID); + } + } + } + } + // } + } + + ///// + ///// If set to true then threads and stuff should try to make a graceful exit + ///// + //public bool PleaseShutdown + //{ + // get { return _PleaseShutdown; } + // set { _PleaseShutdown = value; } + //} + //private bool _PleaseShutdown = false; + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs new file mode 100644 index 0000000000..0fcabab723 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs @@ -0,0 +1,238 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// This class does maintenance on script engine. + /// + public class MaintenanceThread : iScriptEngineFunctionModule + { + //public ScriptEngine m_ScriptEngine; + private int MaintenanceLoopms; + private int MaintenanceLoopTicks_ScriptLoadUnload; + private int MaintenanceLoopTicks_Other; + + + public MaintenanceThread() + { + //m_ScriptEngine = _ScriptEngine; + + ReadConfig(); + + // Start maintenance thread + StartMaintenanceThread(); + } + + ~MaintenanceThread() + { + StopMaintenanceThread(); + } + + public void ReadConfig() + { + // Bad hack, but we need a m_ScriptEngine :) + lock (ScriptEngine.ScriptEngines) + { + foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines) + { + MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50); + MaintenanceLoopTicks_ScriptLoadUnload = + m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_ScriptLoadUnload", 1); + MaintenanceLoopTicks_Other = + m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_Other", 10); + + return; + } + } + } + + #region " Maintenance thread " + /// + /// Maintenance thread. Enforcing max execution time for example. + /// + public Thread MaintenanceThreadThread; + + /// + /// Starts maintenance thread + /// + private void StartMaintenanceThread() + { + if (MaintenanceThreadThread == null) + { + MaintenanceThreadThread = new Thread(MaintenanceLoop); + MaintenanceThreadThread.Name = "ScriptMaintenanceThread"; + MaintenanceThreadThread.IsBackground = true; + MaintenanceThreadThread.Start(); + OpenSim.Framework.ThreadTracker.Add(MaintenanceThreadThread); + } + } + + /// + /// Stops maintenance thread + /// + private void StopMaintenanceThread() + { +#if DEBUG + //m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: StopMaintenanceThread() called"); +#endif + //PleaseShutdown = true; + Thread.Sleep(100); + try + { + if (MaintenanceThreadThread != null && MaintenanceThreadThread.IsAlive) + { + MaintenanceThreadThread.Abort(); + } + } + catch (Exception ex) + { + //m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: Exception stopping maintenence thread: " + ex.ToString()); + } + } + + private ScriptEngine lastScriptEngine; // Keep track of what ScriptEngine instance we are at so we can give exception + /// + /// A thread should run in this loop and check all running scripts + /// + public void MaintenanceLoop() + { + //if (m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens < MaintenanceLoopms) + // m_ScriptEngine.Log.Warn("[" + m_ScriptEngine.ScriptEngineName + "]: " + + // "Configuration error: MaxEventExecutionTimeMs is less than MaintenanceLoopms. The Maintenance Loop will only check scripts once per run."); + + long Last_maxFunctionExecutionTimens = 0; // DateTime.Now.Ticks; + long Last_ReReadConfigFilens = DateTime.Now.Ticks; + int MaintenanceLoopTicks_ScriptLoadUnload_Count = 0; + int MaintenanceLoopTicks_Other_Count = 0; + bool MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = false; + bool MaintenanceLoopTicks_Other_ResetCount = false; + + while (true) + { + try + { + while (true) + { + System.Threading.Thread.Sleep(MaintenanceLoopms); // Sleep before next pass + + // Reset counters? + if (MaintenanceLoopTicks_ScriptLoadUnload_ResetCount) + { + MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = false; + MaintenanceLoopTicks_ScriptLoadUnload_Count = 0; + } + if (MaintenanceLoopTicks_Other_ResetCount) + { + MaintenanceLoopTicks_Other_ResetCount = false; + MaintenanceLoopTicks_Other_Count = 0; + } + + // Increase our counters + MaintenanceLoopTicks_ScriptLoadUnload_Count++; + MaintenanceLoopTicks_Other_Count++; + + + //lock (ScriptEngine.ScriptEngines) + //{ + foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines)) + { + lastScriptEngine = m_ScriptEngine; + // Re-reading config every x seconds + if (MaintenanceLoopTicks_Other_Count >= MaintenanceLoopTicks_Other) + { + MaintenanceLoopTicks_Other_ResetCount = true; + if (m_ScriptEngine.RefreshConfigFilens > 0) + { + // Check if its time to re-read config + if (DateTime.Now.Ticks - Last_ReReadConfigFilens > + m_ScriptEngine.RefreshConfigFilens) + { + //Console.WriteLine("Time passed: " + (DateTime.Now.Ticks - Last_ReReadConfigFilens) + ">" + m_ScriptEngine.RefreshConfigFilens ); + // Its time to re-read config file + m_ScriptEngine.ReadConfig(); + Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time + } + + + // Adjust number of running script threads if not correct + if (m_ScriptEngine.m_EventQueueManager != null) + m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads(); + + // Check if any script has exceeded its max execution time + if (EventQueueManager.EnforceMaxExecutionTime) + { + // We are enforcing execution time + if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens > + EventQueueManager.maxFunctionExecutionTimens) + { + // Its time to check again + m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check + Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time + } + } + } + } + if (MaintenanceLoopTicks_ScriptLoadUnload_Count >= MaintenanceLoopTicks_ScriptLoadUnload) + { + MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = true; + // LOAD / UNLOAD SCRIPTS + if (m_ScriptEngine.m_ScriptManager != null) + m_ScriptEngine.m_ScriptManager.DoScriptLoadUnload(); + } + } + //} + } + } + catch (Exception ex) + { + if (lastScriptEngine != null) + lastScriptEngine.Log.Error("[" + lastScriptEngine.ScriptEngineName + "]: Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: " + ex.ToString()); + Thread.Sleep(5000); + } + } + } + #endregion + + ///// + ///// If set to true then threads and stuff should try to make a graceful exit + ///// + //public bool PleaseShutdown + //{ + // get { return _PleaseShutdown; } + // set { _PleaseShutdown = value; } + //} + //private bool _PleaseShutdown = false; + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs new file mode 100644 index 0000000000..0d551c6681 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs @@ -0,0 +1,183 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// This is the root object for ScriptEngine. Objects access each other trough this class. + /// + /// + [Serializable] + public abstract class ScriptEngine : IRegionModule, OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.ScriptEngine, iScriptEngineFunctionModule + { + private readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public static List ScriptEngines = new List(); + public Scene World; + public EventManager m_EventManager; // Handles and queues incoming events from OpenSim + public EventQueueManager m_EventQueueManager; // Executes events, handles script threads + public ScriptManager m_ScriptManager; // Load, unload and execute scripts + public AppDomainManager m_AppDomainManager; // Handles loading/unloading of scripts into AppDomains + public AsyncLSLCommandManager m_ASYNCLSLCommandManager; // Asyncronous LSL commands (commands that returns with an event) + public static MaintenanceThread m_MaintenanceThread; // Thread that does different kinds of maintenance, for example refreshing config and killing scripts that has been running too long + + public IConfigSource ConfigSource; + public IConfig ScriptConfigSource; + public abstract string ScriptEngineName { get; } + + /// + /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. + /// + public int RefreshConfigFileSeconds { + get { return (int)(RefreshConfigFilens / 10000000); } + set { RefreshConfigFilens = value * 10000000; } + } + public long RefreshConfigFilens; + + public ScriptManager GetScriptManager() + { + return _GetScriptManager(); + } + + public abstract ScriptManager _GetScriptManager(); + + public log4net.ILog Log + { + get { return m_log; } + } + + public ScriptEngine() + { + Common.mySE = this; // For logging, just need any instance, doesn't matter + lock (ScriptEngines) + { + ScriptEngines.Add(this); // Keep a list of ScriptEngines for shared threads to process all instances + } + } + + public void InitializeEngine(Scene Sceneworld, IConfigSource config, bool HookUpToServer, ScriptManager newScriptManager) + { + World = Sceneworld; + ConfigSource = config; + m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing"); + + // Make sure we have config + if (ConfigSource.Configs[ScriptEngineName] == null) + ConfigSource.AddConfig(ScriptEngineName); + ScriptConfigSource = ConfigSource.Configs[ScriptEngineName]; + + //m_log.Info("[" + ScriptEngineName + "]: InitializeEngine"); + + // Create all objects we'll be using + m_EventQueueManager = new EventQueueManager(this); + m_EventManager = new EventManager(this, HookUpToServer); + // We need to start it + newScriptManager.Start(); + m_ScriptManager = newScriptManager; + m_AppDomainManager = new AppDomainManager(this); + m_ASYNCLSLCommandManager = new AsyncLSLCommandManager(this); + if (m_MaintenanceThread == null) + m_MaintenanceThread = new MaintenanceThread(); + + m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\""); + ReadConfig(); + + // Should we iterate the region for scripts that needs starting? + // Or can we assume we are loaded before anything else so we can use proper events? + } + + public void Shutdown() + { + // We are shutting down + lock (ScriptEngines) + { + ScriptEngines.Remove(this); + } + } + + ScriptServerInterfaces.RemoteEvents ScriptServerInterfaces.ScriptEngine.EventManager() + { + return this.m_EventManager; + } + + public void ReadConfig() + { +#if DEBUG + //m_log.Debug("[" + ScriptEngineName + "]: Refreshing configuration for all modules"); +#endif + RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30); + + + // Create a new object (probably not necessary?) +// ScriptConfigSource = ConfigSource.Configs[ScriptEngineName]; + + if (m_EventQueueManager != null) m_EventQueueManager.ReadConfig(); + if (m_EventManager != null) m_EventManager.ReadConfig(); + if (m_ScriptManager != null) m_ScriptManager.ReadConfig(); + if (m_AppDomainManager != null) m_AppDomainManager.ReadConfig(); + if (m_ASYNCLSLCommandManager != null) m_ASYNCLSLCommandManager.ReadConfig(); + if (m_MaintenanceThread != null) m_MaintenanceThread.ReadConfig(); + } + + #region IRegionModule + + public abstract void Initialise(Scene scene, IConfigSource config); + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "Common." + ScriptEngineName; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs new file mode 100644 index 0000000000..7939219834 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs @@ -0,0 +1,435 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + /// + /// Loads scripts + /// Compiles them if necessary + /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution) + /// + /// + + // This class is as close as you get to the script without being inside script class. It handles all the dirty work for other classes. + // * Keeps track of running scripts + // * Compiles script if necessary (through "Compiler") + // * Loads script (through "AppDomainManager" called from for example "EventQueueManager") + // * Executes functions inside script (called from for example "EventQueueManager" class) + // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager") + // * Dedicated load/unload thread, and queues loading/unloading. + // This so that scripts starting or stopping will not slow down other theads or whole system. + // + [Serializable] + public abstract class ScriptManager : iScriptEngineFunctionModule + { + #region Declares + + private Thread scriptLoadUnloadThread; + private static Thread staticScriptLoadUnloadThread; + private int scriptLoadUnloadThread_IdleSleepms; + private Queue LUQueue = new Queue(); + private static bool PrivateThread; + private int LoadUnloadMaxQueueSize; + private Object scriptLock = new Object(); + + // Load/Unload structure + private struct LUStruct + { + public uint localID; + public LLUUID itemID; + public string script; + public LUType Action; + } + + private enum LUType + { + Unknown = 0, + Load = 1, + Unload = 2 + } + + // Object> + // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. + // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! + public Dictionary> Scripts = + new Dictionary>(); + + public Scene World + { + get { return m_scriptEngine.World; } + } + + #endregion + + public void ReadConfig() + { + scriptLoadUnloadThread_IdleSleepms = m_scriptEngine.ScriptConfigSource.GetInt("ScriptLoadUnloadLoopms", 30); + // TODO: Requires sharing of all ScriptManagers to single thread + PrivateThread = true; // m_scriptEngine.ScriptConfigSource.GetBoolean("PrivateScriptLoadUnloadThread", false); + LoadUnloadMaxQueueSize = m_scriptEngine.ScriptConfigSource.GetInt("LoadUnloadMaxQueueSize", 100); + } + + #region Object init/shutdown + + public ScriptEngineBase.ScriptEngine m_scriptEngine; + + public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + } + public abstract void Initialize(); + public void Start() + { + ReadConfig(); + Initialize(); + + AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); + + // + // CREATE THREAD + // Private or shared + // + if (PrivateThread) + { + // Assign one thread per region + //scriptLoadUnloadThread = StartScriptLoadUnloadThread(); + } + else + { + // Shared thread - make sure one exist, then assign it to the private + if (staticScriptLoadUnloadThread == null) + { + //staticScriptLoadUnloadThread = StartScriptLoadUnloadThread(); + } + scriptLoadUnloadThread = staticScriptLoadUnloadThread; + } + } + + private static int privateThreadCount = 0; + private Thread StartScriptLoadUnloadThread() + { + Thread t = new Thread(ScriptLoadUnloadThreadLoop); + string name = "ScriptLoadUnloadThread:"; + if (PrivateThread) + { + name += "Private:" + privateThreadCount; + privateThreadCount++; + } + else + { + name += "Shared"; + } + t.Name = name; + t.IsBackground = true; + t.Priority = ThreadPriority.Normal; + t.Start(); + OpenSim.Framework.ThreadTracker.Add(t); + return t; + } + + ~ScriptManager() + { + // Abort load/unload thread + try + { + //PleaseShutdown = true; + //Thread.Sleep(100); + if (scriptLoadUnloadThread != null && scriptLoadUnloadThread.IsAlive == true) + { + scriptLoadUnloadThread.Abort(); + //scriptLoadUnloadThread.Join(); + } + } + catch + { + } + } + + #endregion + + #region Load / Unload scripts (Thread loop) + + private void ScriptLoadUnloadThreadLoop() + { + try + { + while (true) + { + if (LUQueue.Count == 0) + Thread.Sleep(scriptLoadUnloadThread_IdleSleepms); + //if (PleaseShutdown) + // return; + DoScriptLoadUnload(); + } + } + catch (ThreadAbortException tae) + { + string a = tae.ToString(); + a = String.Empty; + // Expected + } + } + + public void DoScriptLoadUnload() + { + if (LUQueue.Count > 0) + { + LUStruct item = LUQueue.Dequeue(); + lock (startStopLock) // Lock so we have only 1 thread working on loading/unloading of scripts + { + if (item.Action == LUType.Unload) + { + _StopScript(item.localID, item.itemID); + } + if (item.Action == LUType.Load) + { + _StartScript(item.localID, item.itemID, item.script); + } + } + } + + } + + #endregion + + #region Helper functions + + private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name); + return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null; + } + + #endregion + + + + #region Start/Stop/Reset script + + private readonly Object startStopLock = new Object(); + + /// + /// Fetches, loads and hooks up a script to an objects events + /// + /// + /// + public void StartScript(uint localID, LLUUID itemID, string Script) + { + if (LUQueue.Count >= LoadUnloadMaxQueueSize) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: ERROR: Load/unload queue item count is at " + LUQueue.Count + ". Config variable \"LoadUnloadMaxQueueSize\" is set to " + LoadUnloadMaxQueueSize + ", so ignoring new script."); + return; + } + + LUStruct ls = new LUStruct(); + ls.localID = localID; + ls.itemID = itemID; + ls.script = Script; + ls.Action = LUType.Load; + LUQueue.Enqueue(ls); + } + + /// + /// Disables and unloads a script + /// + /// + /// + public void StopScript(uint localID, LLUUID itemID) + { + LUStruct ls = new LUStruct(); + ls.localID = localID; + ls.itemID = itemID; + ls.Action = LUType.Unload; + LUQueue.Enqueue(ls); + } + + // Create a new instance of the compiler (reuse) + //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler(); + + public abstract void _StartScript(uint localID, LLUUID itemID, string Script); + public abstract void _StopScript(uint localID, LLUUID itemID); + + + #endregion + + #region Perform event execution in script + + /// + /// Execute a LL-event-function in Script + /// + /// Object the script is located in + /// Script ID + /// Name of function + /// Arguments to pass to function + internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, EventQueueManager.Queue_llDetectParams_Struct qParams, object[] args) + { + //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined + ///#if DEBUG + /// Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName); + ///#endif + // Execute a function in the script + //m_scriptEngine.Log.Info("[" + ScriptEngineName + "]: Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); + //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID); + IScript Script = GetScript(localID, itemID); + if (Script == null) + { + return; + } + //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined + ///#if DEBUG + /// Console.WriteLine("ScriptEngine: Executing event: " + FunctionName); + ///#endif + // Must be done in correct AppDomain, so leaving it up to the script itself + Script.llDetectParams = qParams; + Script.Exec.ExecuteEvent(FunctionName, args); + } + + #endregion + + #region Internal functions to keep track of script + + public Dictionary.KeyCollection GetScriptKeys(uint localID) + { + if (Scripts.ContainsKey(localID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + + return Obj.Keys; + } + + public IScript GetScript(uint localID, LLUUID itemID) + { + lock (scriptLock) + { + if (Scripts.ContainsKey(localID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == false) + return null; + + // Get script + IScript Script; + Obj.TryGetValue(itemID, out Script); + return Script; + } + } + + public void SetScript(uint localID, LLUUID itemID, IScript Script) + { + lock (scriptLock) + { + // Create object if it doesn't exist + if (Scripts.ContainsKey(localID) == false) + { + Scripts.Add(localID, new Dictionary()); + } + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == true) + Obj.Remove(itemID); + + // Add to object + Obj.Add(itemID, Script); + } + } + + public void RemoveScript(uint localID, LLUUID itemID) + { + // Don't have that object? + if (Scripts.ContainsKey(localID) == false) + return; + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == true) + Obj.Remove(itemID); + } + + #endregion + + + public void ResetScript(uint localID, LLUUID itemID) + { + string script = GetScript(localID, itemID).Source; + StopScript(localID, itemID); + StartScript(localID, itemID, script); + } + + + #region Script serialization/deserialization + + public void GetSerializedScript(uint localID, LLUUID itemID) + { + // Serialize the script and return it + // Should not be a problem + FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID); + BinaryFormatter b = new BinaryFormatter(); + b.Serialize(fs, GetScript(localID, itemID)); + fs.Close(); + } + + public void PutSerializedScript(uint localID, LLUUID itemID) + { + // Deserialize the script and inject it into an AppDomain + + // How to inject into an AppDomain? + } + + #endregion + + ///// + ///// If set to true then threads and stuff should try to make a graceful exit + ///// + //public bool PleaseShutdown + //{ + // get { return _PleaseShutdown; } + // set { _PleaseShutdown = value; } + //} + //private bool _PleaseShutdown = false; + + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs new file mode 100644 index 0000000000..516d76a723 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs @@ -0,0 +1,40 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +{ + public interface iScriptEngineFunctionModule + { + void ReadConfig(); +// bool PleaseShutdown { get; set; } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs b/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs index 1e8917cbed..26e479c314 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptServerInterfaces.cs @@ -1,52 +1,90 @@ -using libsecondlife; -using OpenSim.Framework; - -namespace OpenSim.Region.ScriptEngine.Common -{ - public class ScriptServerInterfaces - { - public interface RemoteEvents - { - void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient); - void OnRezScript(uint localID, LLUUID itemID, string script); - void OnRemoveScript(uint localID, LLUUID itemID); - void state_exit(uint localID, LLUUID itemID); - void touch(uint localID, LLUUID itemID); - void touch_end(uint localID, LLUUID itemID); - void collision_start(uint localID, LLUUID itemID); - void collision(uint localID, LLUUID itemID); - void collision_end(uint localID, LLUUID itemID); - void land_collision_start(uint localID, LLUUID itemID); - void land_collision(uint localID, LLUUID itemID); - void land_collision_end(uint localID, LLUUID itemID); - void timer(uint localID, LLUUID itemID); - void listen(uint localID, LLUUID itemID); - void on_rez(uint localID, LLUUID itemID); - void sensor(uint localID, LLUUID itemID); - void no_sensor(uint localID, LLUUID itemID); - void control(uint localID, LLUUID itemID); - void money(uint localID, LLUUID itemID); - void email(uint localID, LLUUID itemID); - void at_target(uint localID, LLUUID itemID); - void not_at_target(uint localID, LLUUID itemID); - void at_rot_target(uint localID, LLUUID itemID); - void not_at_rot_target(uint localID, LLUUID itemID); - void run_time_permissions(uint localID, LLUUID itemID); - void changed(uint localID, LLUUID itemID); - void attach(uint localID, LLUUID itemID); - void dataserver(uint localID, LLUUID itemID); - void link_message(uint localID, LLUUID itemID); - void moving_start(uint localID, LLUUID itemID); - void moving_end(uint localID, LLUUID itemID); - void object_rez(uint localID, LLUUID itemID); - void remote_data(uint localID, LLUUID itemID); - void http_response(uint localID, LLUUID itemID); - } - - public interface ServerRemotingObject - { - RemoteEvents Events(); - } - - } -} +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public class ScriptServerInterfaces + { + public interface RemoteEvents + { + void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient); + void OnRezScript(uint localID, LLUUID itemID, string script); + void OnRemoveScript(uint localID, LLUUID itemID); + void state_exit(uint localID, LLUUID itemID); + void touch(uint localID, LLUUID itemID); + void touch_end(uint localID, LLUUID itemID); + void collision_start(uint localID, LLUUID itemID); + void collision(uint localID, LLUUID itemID); + void collision_end(uint localID, LLUUID itemID); + void land_collision_start(uint localID, LLUUID itemID); + void land_collision(uint localID, LLUUID itemID); + void land_collision_end(uint localID, LLUUID itemID); + void timer(uint localID, LLUUID itemID); + void listen(uint localID, LLUUID itemID); + void on_rez(uint localID, LLUUID itemID); + void sensor(uint localID, LLUUID itemID); + void no_sensor(uint localID, LLUUID itemID); + void control(uint localID, LLUUID itemID); + void money(uint localID, LLUUID itemID); + void email(uint localID, LLUUID itemID); + void at_target(uint localID, LLUUID itemID); + void not_at_target(uint localID, LLUUID itemID); + void at_rot_target(uint localID, LLUUID itemID); + void not_at_rot_target(uint localID, LLUUID itemID); + void run_time_permissions(uint localID, LLUUID itemID); + void changed(uint localID, LLUUID itemID); + void attach(uint localID, LLUUID itemID); + void dataserver(uint localID, LLUUID itemID); + void link_message(uint localID, LLUUID itemID); + void moving_start(uint localID, LLUUID itemID); + void moving_end(uint localID, LLUUID itemID); + void object_rez(uint localID, LLUUID itemID); + void remote_data(uint localID, LLUUID itemID); + void http_response(uint localID, LLUUID itemID); + } + + public interface ServerRemotingObject + { + RemoteEvents Events(); + } + + public interface ScriptEngine + { + RemoteEvents EventManager(); + void InitializeEngine(Scene Sceneworld, IConfigSource config, bool DontHookUp, ScriptManager newScriptManager); + ScriptManager GetScriptManager(); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/TRPC/MyBase.cs b/OpenSim/Region/ScriptEngine/Common/TRPC/MyBase.cs new file mode 100644 index 0000000000..16f77a36a2 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/TRPC/MyBase.cs @@ -0,0 +1,38 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + class MyBase + { + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/TRPC/TCPClient.cs b/OpenSim/Region/ScriptEngine/Common/TRPC/TCPClient.cs new file mode 100644 index 0000000000..1fd7a258a6 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/TRPC/TCPClient.cs @@ -0,0 +1,153 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + public class TCPClient : TCPCommon.ClientInterface + { + + public TCPClient() + { + } + private readonly Dictionary Clients = new Dictionary(); + private int ClientCount = 0; + + + public event TCPCommon.ClientConnectedDelegate ClientConnected; + public event TCPCommon.DataReceivedDelegate DataReceived; + public event TCPCommon.DataSentDelegate DataSent; + public event TCPCommon.CloseDelegate Close; + public event TCPCommon.ConnectErrorDelegate ConnectError; + + + /// + /// Creates client connection + /// + public void Connect(string RemoteHost, int RemotePort) + { + Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(RemoteHost), RemotePort); + //newsock.BeginConnect(ipe, new AsyncCallback(asyncConnected), newsock); + newsock.Connect(ipe); + } + public int ConnectAndReturnID(string RemoteHost, int RemotePort) + { + Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(RemoteHost), RemotePort); + //newsock.BeginConnect(ipe, new AsyncCallback(asyncConnected), newsock); + newsock.Connect(ipe); + return ProcessConnection(newsock); + } + + + public void Disconnect(int ID) + { + Clients[ID].Disconnect(); + } + + void asyncConnected(IAsyncResult iar) + { + Socket client = (Socket)iar.AsyncState; + client.EndConnect(iar); + ProcessConnection(client); + } + + private int ProcessConnection(Socket client) + { + try + { + + + + int id = ClientCount++; + TCPSocket S = new TCPSocket(id, client); + + // Add to dictionary + Clients.Add(id, S); + + // Add event handlers + S.Close += new TCPSocket.CloseDelegate(S_Close); + S.DataReceived += new TCPSocket.DataReceivedDelegate(S_DataReceived); + S.DataSent += new TCPSocket.DataSentDelegate(S_DataSent); + + // Start it + S.Start(); + + Debug.WriteLine("Connection established: " + client.RemoteEndPoint.ToString()); + + // Fire Connected-event + if (ClientConnected != null) + ClientConnected(id, client.RemoteEndPoint); + + return id; + } + catch (SocketException sex) + { + if (ConnectError != null) + ConnectError(sex.Message); + } + return -1; + } + + + + + void S_DataSent(int ID, int length) + { + if (DataSent != null) + DataSent(ID, length); + } + + void S_DataReceived(int ID, byte[] data, int offset, int length) + { + if (DataReceived != null) + DataReceived(ID, data, offset, length); + } + + void S_Close(int ID) + { + if (Close != null) + Close(ID); + Clients.Remove(ID); + } + + public void Send(int clientID, byte[] data, int offset, int len) + { + Clients[clientID].Send(clientID, data, offset, len); + } + + + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Common/TRPC/TCPCommon.cs b/OpenSim/Region/ScriptEngine/Common/TRPC/TCPCommon.cs new file mode 100644 index 0000000000..f3a55baca4 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/TRPC/TCPCommon.cs @@ -0,0 +1,61 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + public class TCPCommon + { + public delegate void ClientConnectedDelegate(int ID, System.Net.EndPoint Remote); + public delegate void DataReceivedDelegate(int ID, byte[] data, int offset, int length); + public delegate void DataSentDelegate(int ID, int length); + public delegate void CloseDelegate(int ID); + public delegate void ConnectErrorDelegate(string Reason); + + + public interface ServerAndClientInterface + { + void Send(int clientID, byte[] data, int offset, int len); + event ClientConnectedDelegate ClientConnected; + event DataReceivedDelegate DataReceived; + event DataSentDelegate DataSent; + event CloseDelegate Close; + } + public interface ClientInterface : ServerAndClientInterface + { + event TCPCommon.ConnectErrorDelegate ConnectError; + void Connect(string RemoteHost, int RemotePort); + void Disconnect(int ID); + } + public interface ServerInterface : ServerAndClientInterface + { + void StartListen(); + void StopListen(); + } + + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Common/TRPC/TCPServer.cs b/OpenSim/Region/ScriptEngine/Common/TRPC/TCPServer.cs new file mode 100644 index 0000000000..da16da87dc --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/TRPC/TCPServer.cs @@ -0,0 +1,134 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Sockets; +using TCPCommon=OpenSim.Region.ScriptEngine.Common.TRPC.TCPCommon; + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + public class TCPServer: TCPCommon.ServerInterface + { + public readonly int LocalPort; + public TCPServer(int localPort) + { + LocalPort = localPort; + } + + private Socket server; + + /// + /// Starts listening for new connections + /// + public void StartListen() + { + server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint ipe = new IPEndPoint(IPAddress.Any, LocalPort); + server.Bind(ipe); + server.Listen(10); + server.BeginAccept(new AsyncCallback(AsyncAcceptConnections), server); + } + /// + /// Stops listening for new connections + /// + public void StopListen() + { + server.Close(); + server = null; + } + + private readonly Dictionary Clients = new Dictionary(); + private int ClientCount = 0; + + + public event TCPCommon.ClientConnectedDelegate ClientConnected; + public event TCPCommon.DataReceivedDelegate DataReceived; + public event TCPCommon.DataSentDelegate DataSent; + public event TCPCommon.CloseDelegate Close; + + /// + /// Async callback for new connections + /// + /// + private void AsyncAcceptConnections(IAsyncResult ar) + { + int id = ClientCount++; + Socket oldserver = (Socket)ar.AsyncState; + Socket client = oldserver.EndAccept(ar); + TCPSocket S = new TCPSocket(id, client); + + // Add to dictionary + Clients.Add(id, S); + + // Add event handlers + S.Close += new TCPSocket.CloseDelegate(S_Close); + S.DataReceived += new TCPSocket.DataReceivedDelegate(S_DataReceived); + S.DataSent += new TCPSocket.DataSentDelegate(S_DataSent); + + // Start it + S.Start(); + + Debug.WriteLine("Connection received: " + client.RemoteEndPoint.ToString()); + + // Fire Connected-event + if (ClientConnected != null) + ClientConnected(id, client.RemoteEndPoint); + + } + + void S_DataSent(int ID, int length) + { + if (DataSent != null) + DataSent(ID, length); + } + + void S_DataReceived(int ID, byte[] data, int offset, int length) + { + if (DataReceived != null) + DataReceived(ID, data, offset, length); + } + + void S_Close(int ID) + { + if (Close != null) + Close(ID); + Clients.Remove(ID); + } + + public void Send(int clientID, byte[] data, int offset, int len) + { + Clients[clientID].Send(clientID, data, offset, len); + } + + + + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Common/TRPC/TCPSocket.cs b/OpenSim/Region/ScriptEngine/Common/TRPC/TCPSocket.cs new file mode 100644 index 0000000000..1e4743961f --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/TRPC/TCPSocket.cs @@ -0,0 +1,114 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Net.Sockets; + +namespace OpenSim.Region.ScriptEngine.Common.TRPC +{ + public class TCPSocket + { + + public readonly Socket Client; + public readonly int ID; + + public delegate void DataReceivedDelegate(int ID, byte[] data, int offset, int length); + public delegate void DataSentDelegate(int ID, int length); + public delegate void CloseDelegate(int ID); + public event DataReceivedDelegate DataReceived; + public event DataSentDelegate DataSent; + public event CloseDelegate Close; + + private byte[] RecvQueue = new byte[4096]; + private int RecvQueueSize = 4096; + + public TCPSocket(int id, Socket client) + { + ID = id; + Client = client; + } + public void Start() + { + // Start listening + BeginReceive(); + } + + private void BeginReceive() + { + Client.BeginReceive(RecvQueue, 0, RecvQueueSize, SocketFlags.None, new AsyncCallback(asyncDataReceived), Client); + } + + /// + /// Callback for successful receive (or connection close) + /// + /// + private void asyncDataReceived(IAsyncResult ar) + { + Socket client = (Socket)ar.AsyncState; + int recv = client.EndReceive(ar); + + // Is connection closed? + if (recv == 0) + { + client.Close(); + Close(ID); + return; + } + + // Call receive event + DataReceived(ID, RecvQueue, 0, recv); + + // Start new receive + BeginReceive(); + + } + + + public void Send(int clientID, byte[] data, int offset, int len) + { + Client.BeginSend(data, offset, len, SocketFlags.None, new AsyncCallback(asyncDataSent), Client); + } + + /// + /// Callback for successful send + /// + /// + void asyncDataSent(IAsyncResult ar) + { + Socket client = (Socket)ar.AsyncState; + int sent = client.EndSend(ar); + DataSent(ID, sent); + } + + public void Disconnect() + { + Client.Close(); + Close(ID); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Common/TRPC_Remote.cs b/OpenSim/Region/ScriptEngine/Common/TRPC_Remote.cs new file mode 100644 index 0000000000..5752e2b1a7 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Common/TRPC_Remote.cs @@ -0,0 +1,205 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using libsecondlife; +using OpenSim.Region.ScriptEngine.Common.TRPC; + +namespace OpenSim.Region.ScriptEngine.Common +{ + public class TRPC_Remote + { + public readonly int MaxQueueSize = 1024 * 10; + public readonly TCPCommon.ServerAndClientInterface TCPS; + + public delegate void ReceiveCommandDelegate(int ID, string Command, params object[] p); + public event ReceiveCommandDelegate ReceiveCommand; + System.Collections.Generic.Dictionary TypeDictionary = new Dictionary(); + Type[] Types = + { + typeof(System.String), + typeof(System.Int16), + typeof(System.Int32), + typeof(System.Int64), + typeof(System.Double), + typeof(System.Decimal), + typeof(System.Array), + typeof(LLUUID), + typeof(System.UInt16), + typeof(System.UInt32), + typeof(System.UInt64) + }; + + // TODO: Maybe we should move queue into TCPSocket so we won't have to keep one queue instance per connection + private System.Collections.Generic.Dictionary InQueue = new Dictionary(); + private class InQueueStruct + { + public byte[] Queue; + public int QueueSize; + public object QueueLockObject = new object(); + } + + public TRPC_Remote(TCPCommon.ServerAndClientInterface TCPClientOrServer) + { + TCPS = TCPClientOrServer; + TCPS.Close += new TCPCommon.CloseDelegate(TCPS_Close); + TCPS.ClientConnected += new TCPCommon.ClientConnectedDelegate(TCPS_ClientConnected); + TCPS.DataReceived += new TCPCommon.DataReceivedDelegate(TCPS_DataReceived); + //TCPS.StartListen(); + + // Make a lookup dictionary for types + foreach (Type t in Types) + { + TypeDictionary.Add(t.ToString(), t); + } + } + + void TCPS_ClientConnected(int ID, System.Net.EndPoint Remote) + { + // Create a incoming queue for this connection + InQueueStruct iq = new InQueueStruct(); + iq.Queue = new byte[MaxQueueSize]; + iq.QueueSize = 0; + InQueue.Add(ID, iq); + } + + void TCPS_Close(int ID) + { + // Remove queue + InQueue.Remove(ID); + } + + void TCPS_DataReceived(int ID, byte[] data, int offset, int length) + { + // Copy new data to incoming queue + lock (InQueue[ID].QueueLockObject) + { + Array.Copy(data, offset, InQueue[ID].Queue, InQueue[ID].QueueSize, length); + InQueue[ID].QueueSize += length; + + // Process incoming queue + ProcessQueue(ID); + } + } + + private void ProcessQueue(int ID) + { + + // This is just a temp implementation -- not so fast :) + + InQueueStruct myIQS = InQueue[ID]; + if (myIQS.QueueSize == 0) + return; + + string receivedData = Encoding.ASCII.GetString(myIQS.Queue, 0, myIQS.QueueSize); + Debug.WriteLine("RAW: " + receivedData); + + + byte newLine = 10; + while (true) + { + bool ShouldProcess = false; + int lineEndPos = 0; + + // Look for newline + for (int i = 0; i < myIQS.QueueSize; i++) + { + if (myIQS.Queue[i] == newLine) + { + ShouldProcess = true; + lineEndPos = i; + break; + } + } + + // Process it? + if (!ShouldProcess) + return; + // Yes + string cmdLine = Encoding.ASCII.GetString(myIQS.Queue, 0, lineEndPos); + Debug.WriteLine("Command: " + cmdLine); + + // Fix remaining queue in an inefficient way + byte[] newQueue = new byte[MaxQueueSize]; + Array.Copy(myIQS.Queue, lineEndPos, newQueue, 0, myIQS.QueueSize - lineEndPos); + myIQS.Queue = newQueue; + myIQS.QueueSize -= (lineEndPos + 1); + + // Now back to the command + string[] parts = cmdLine.Split(','); + if (parts.Length > 0) + { + string cmd = parts[0]; + int paramCount = parts.Length - 1; + object[] param = null; + + if (paramCount > 0) + { + // Process all parameters (decoding them from URL encoding) + param = new object[paramCount]; + for (int i = 1; i < parts.Length; i++) + { + string[] spl; + spl = System.Web.HttpUtility.UrlDecode(parts[i]).Split('|'); + string t = spl[0]; + param[i - 1] = Convert.ChangeType(spl[1], TypeLookup(t)); + } + } + + ReceiveCommand(ID, cmd, param); + } + } + } + + private Type TypeLookup(string t) + { + Type ret = TypeDictionary[t]; + if (ret != null) + return ret; + return typeof(object); + } + + public void SendCommand(int ID, string Command, params object[] p) + { + // Call PacketFactory to have it create a packet for us + + //string[] tmpP = new string[p.Length]; + string tmpStr = Command; + for (int i = 0; i < p.Length; i++) + { + tmpStr += "," + p[i].GetType().ToString() + "|" + System.Web.HttpUtility.UrlEncode(p[i].ToString()); // .Replace(",", "%44") + } + tmpStr += "\n"; + byte[] byteData = Encoding.ASCII.GetBytes(tmpStr); + TCPS.Send(ID, byteData, 0, byteData.Length); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs index effcbbea64..e7b33f64c1 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs @@ -1,160 +1,441 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.CodeDom.Compiler; -using System.IO; -using System.Reflection; -using Microsoft.CSharp; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL -{ - public class Compiler - { - - // * Uses "LSL2Converter" to convert LSL to C# if necessary. - // * Compiles C#-code into an assembly - // * Returns assembly name ready for AppDomain load. - // - // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details. - // - - private LSL2CSConverter LSL_Converter = new LSL2CSConverter(); - private CSharpCodeProvider codeProvider = new CSharpCodeProvider(); - private static UInt64 scriptCompileCounter = 0; - - private static int instanceID = new Random().Next(0, int.MaxValue); - // Implemented due to peer preassure --- will cause garbage in ScriptEngines folder ;) - - //private ICodeCompiler icc = codeProvider.CreateCompiler(); - public string CompileFromFile(string LSOFileName) - { - switch (Path.GetExtension(LSOFileName).ToLower()) - { - case ".txt": - case ".lsl": - Common.SendToDebug("Source code is LSL, converting to CS"); - return CompileFromLSLText(File.ReadAllText(LSOFileName)); - case ".cs": - Common.SendToDebug("Source code is CS"); - return CompileFromCSText(File.ReadAllText(LSOFileName)); - default: - throw new Exception("Unknown script type."); - } - } - - /// - /// Converts script from LSL to CS and calls CompileFromCSText - /// - /// LSL script - /// Filename to .dll assembly - public string CompileFromLSLText(string Script) - { - if (Script.Substring(0, 4).ToLower() == "//c#") - { - return CompileFromCSText(Script); - } - else - { - return CompileFromCSText(LSL_Converter.Convert(Script)); - } - } - - /// - /// Compile CS script to .Net assembly (.dll) - /// - /// CS script - /// Filename to .dll assembly - public string CompileFromCSText(string Script) - { - // Output assembly name - scriptCompileCounter++; - string OutFile = - Path.Combine("ScriptEngines", - "DotNetScript_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll"); - try - { - File.Delete(OutFile); - } - catch (Exception e) - { - Console.WriteLine("Exception attempting to delete old compiled script: " + e.ToString()); - } - //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll"); - - // DEBUG - write source to disk - try - { - File.WriteAllText( - Path.Combine("ScriptEngines", "debug_" + Path.GetFileNameWithoutExtension(OutFile) + ".cs"), Script); - } - catch - { - } - - // Do actual compile - CompilerParameters parameters = new CompilerParameters(); - parameters.IncludeDebugInformation = true; - // Add all available assemblies - foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) - { - //Console.WriteLine("Adding assembly: " + asm.Location); - //parameters.ReferencedAssemblies.Add(asm.Location); - } - - string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); - string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location); - //Console.WriteLine("Assembly location: " + rootPath); - parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Common.dll")); - parameters.ReferencedAssemblies.Add(Path.Combine(rootPathSE, "OpenSim.Region.ScriptEngine.DotNetEngine.dll")); - - //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment"); - parameters.GenerateExecutable = false; - parameters.OutputAssembly = OutFile; - parameters.IncludeDebugInformation = false; - CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, Script); - - // Go through errors - // TODO: Return errors to user somehow - if (results.Errors.Count > 0) - { - string errtext = ""; - foreach (CompilerError CompErr in results.Errors) - { - errtext += "Line number " + (CompErr.Line - 1) + - ", Error Number: " + CompErr.ErrorNumber + - ", '" + CompErr.ErrorText + "'\r\n"; - } - throw new Exception(errtext); - } - - - return OutFile; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; +using Microsoft.CSharp; +using Microsoft.VisualBasic; +using Microsoft.JScript; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public class Compiler + { + // * Uses "LSL2Converter" to convert LSL to C# if necessary. + // * Compiles C#-code into an assembly + // * Returns assembly name ready for AppDomain load. + // + // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details. + // + + internal enum enumCompileType + { + lsl = 0, + cs = 1, + vb = 2, + js = 3 + } + + /// + /// This contains number of lines WE use for header when compiling script. User will get error in line x-LinesToRemoveOnError when error occurs. + /// + public int LinesToRemoveOnError = 3; + private enumCompileType DefaultCompileLanguage; + private bool WriteScriptSourceToDebugFile; + private bool CompileWithDebugInformation; + private bool CleanUpOldScriptsOnStartup; + private System.Collections.Generic.Dictionary AllowedCompilers = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + private System.Collections.Generic.Dictionary LanguageMapping = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + + private string FilePrefix; + private string ScriptEnginesPath = "ScriptEngines"; + + private static LSL2CSConverter LSL_Converter = new LSL2CSConverter(); + private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); + private static VBCodeProvider VBcodeProvider = new VBCodeProvider(); + private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider(); + + private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files + private static UInt64 scriptCompileCounter = 0; // And a counter + + public Common.ScriptEngineBase.ScriptEngine m_scriptEngine; + public Compiler(Common.ScriptEngineBase.ScriptEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + ReadConfig(); + } + public bool in_startup = true; + public void ReadConfig() + { + + // Get some config + WriteScriptSourceToDebugFile = m_scriptEngine.ScriptConfigSource.GetBoolean("WriteScriptSourceToDebugFile", true); + CompileWithDebugInformation = m_scriptEngine.ScriptConfigSource.GetBoolean("CompileWithDebugInformation", true); + CleanUpOldScriptsOnStartup = m_scriptEngine.ScriptConfigSource.GetBoolean("CleanUpOldScriptsOnStartup", true); + + // Get file prefix from scriptengine name and make it file system safe: + FilePrefix = m_scriptEngine.ScriptEngineName; + foreach (char c in Path.GetInvalidFileNameChars()) + { + FilePrefix = FilePrefix.Replace(c, '_'); + } + + // First time we start? Delete old files + if (in_startup) + { + in_startup = false; + DeleteOldFiles(); + } + + // Map name and enum type of our supported languages + LanguageMapping.Add(enumCompileType.cs.ToString(), enumCompileType.cs); + LanguageMapping.Add(enumCompileType.vb.ToString(), enumCompileType.vb); + LanguageMapping.Add(enumCompileType.lsl.ToString(), enumCompileType.lsl); + LanguageMapping.Add(enumCompileType.js.ToString(), enumCompileType.js); + + // Allowed compilers + string allowComp = m_scriptEngine.ScriptConfigSource.GetString("AllowedCompilers", "lsl,cs,vb,js"); + AllowedCompilers.Clear(); + +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Allowed languages: " + allowComp); +#endif + + + foreach (string strl in allowComp.Split(',')) + { + string strlan = strl.Trim(" \t".ToCharArray()).ToLower(); + if (!LanguageMapping.ContainsKey(strlan)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler is unable to recognize language type \"" + strlan + "\" specified in \"AllowedCompilers\"."); + } + else + { +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Config OK. Compiler recognized language type \"" + strlan + "\" specified in \"AllowedCompilers\"."); +#endif + } + AllowedCompilers.Add(strlan, true); + } + if (AllowedCompilers.Count == 0) + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!"); + + // Default language + string defaultCompileLanguage = m_scriptEngine.ScriptConfigSource.GetString("DefaultCompileLanguage", "lsl").ToLower(); + + // Is this language recognized at all? + if (!LanguageMapping.ContainsKey(defaultCompileLanguage)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Config error. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is not recognized as a valid language. Changing default to: \"lsl\"."); + defaultCompileLanguage = "lsl"; + } + + // Is this language in allow-list? + if (!AllowedCompilers.ContainsKey(defaultCompileLanguage)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!"); + } + else + { +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Config OK. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is recognized as a valid language."); +#endif + // LANGUAGE IS IN ALLOW-LIST + DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage]; + } + + // We now have an allow-list, a mapping list, and a default language + + } + + /// + /// Delete old script files + /// + private void DeleteOldFiles() + { + + // CREATE FOLDER IF IT DOESNT EXIST + if (!Directory.Exists(ScriptEnginesPath)) + { + try + { + Directory.CreateDirectory(ScriptEnginesPath); + } + catch (Exception ex) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString()); + } + } + + foreach (string file in Directory.GetFiles(ScriptEnginesPath)) + { + //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: FILE FOUND: " + file); + + if (file.ToLower().StartsWith(FilePrefix + "_compiled_") || + file.ToLower().StartsWith(FilePrefix + "_source_")) + { + try + { + File.Delete(file); + } + catch (Exception ex) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying delete old script file \"" + file + "\": " + ex.ToString()); + } + + } + } + + } + + ////private ICodeCompiler icc = codeProvider.CreateCompiler(); + //public string CompileFromFile(string LSOFileName) + //{ + // switch (Path.GetExtension(LSOFileName).ToLower()) + // { + // case ".txt": + // case ".lsl": + // Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS"); + // return CompileFromLSLText(File.ReadAllText(LSOFileName)); + // case ".cs": + // Common.ScriptEngineBase.Common.SendToDebug("Source code is CS"); + // return CompileFromCSText(File.ReadAllText(LSOFileName)); + // default: + // throw new Exception("Unknown script type."); + // } + //} + + /// + /// Converts script from LSL to CS and calls CompileFromCSText + /// + /// LSL script + /// Filename to .dll assembly + public string PerformScriptCompile(string Script) + { + enumCompileType l = DefaultCompileLanguage; + + + if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture)) + l = enumCompileType.cs; + if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture)) + { + l = enumCompileType.vb; + // We need to remove //vb, it won't compile with that + + Script = Script.Substring(4, Script.Length - 4); + } + if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture)) + l = enumCompileType.lsl; + + if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture)) + l = enumCompileType.js; + + if (!AllowedCompilers.ContainsKey(l.ToString())) + { + // Not allowed to compile to this language! + string errtext = String.Empty; + errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!"; + throw new Exception(errtext); + } + + string compileScript = Script; + + if (l == enumCompileType.lsl) + { + // Its LSL, convert it to C# + compileScript = LSL_Converter.Convert(Script); + l = enumCompileType.cs; + } + + switch (l) + { + case enumCompileType.cs: + compileScript = CreateCSCompilerScript(compileScript); + break; + case enumCompileType.vb: + compileScript = CreateVBCompilerScript(compileScript); + break; + case enumCompileType.js: + compileScript = CreateJSCompilerScript(compileScript); + break; + } + return CompileFromDotNetText(compileScript, l); + } + + private static string CreateJSCompilerScript(string compileScript) + { + compileScript = String.Empty + + "import OpenSim.Region.ScriptEngine.Common; import System.Collections.Generic;\r\n" + + "package SecondLife {\r\n" + + "class Script extends OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { \r\n" + + compileScript + + "} }\r\n"; + return compileScript; + } + + private static string CreateCSCompilerScript(string compileScript) + { + compileScript = String.Empty + + "using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;\r\n" + + String.Empty + "namespace SecondLife { " + + String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { \r\n" + + @"public Script() { } " + + compileScript + + "} }\r\n"; + return compileScript; + } + + private static string CreateVBCompilerScript(string compileScript) + { + compileScript = String.Empty + + "Imports OpenSim.Region.ScriptEngine.Common: Imports System.Collections.Generic: " + + String.Empty + "NameSpace SecondLife:" + + String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.Common.LSL_BaseClass: " + + "\r\nPublic Sub New()\r\nEnd Sub: " + + compileScript + + ":End Class :End Namespace\r\n"; + return compileScript; + } + + /// + /// Compile .NET script to .Net assembly (.dll) + /// + /// CS script + /// Filename to .dll assembly + internal string CompileFromDotNetText(string Script, enumCompileType lang) + { + string ext = "." + lang.ToString(); + + // Output assembly name + scriptCompileCounter++; + string OutFile = + Path.Combine("ScriptEngines", + FilePrefix + "_compiled_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll"); +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Starting compile of \"" + OutFile + "\"."); +#endif + try + { + File.Delete(OutFile); + } + catch (Exception e) // NOTLEGIT - Should be just catching FileIOException + { + //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); + throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); + } + //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll"); + + // DEBUG - write source to disk + if (WriteScriptSourceToDebugFile) + { + string srcFileName = FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext; + try + { + File.WriteAllText( + Path.Combine("ScriptEngines", srcFileName), + Script); + } + catch (Exception ex) // NOTLEGIT - Should be just catching FileIOException + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception while trying to write script source to file \"" + srcFileName + "\": " + ex.ToString()); + } + } + + // Do actual compile + CompilerParameters parameters = new CompilerParameters(); + + parameters.IncludeDebugInformation = true; + + // Add all available assemblies + foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) + { + //Console.WriteLine("Adding assembly: " + asm.Location); + //parameters.ReferencedAssemblies.Add(asm.Location); + } + + string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); + string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location); + //Console.WriteLine("Assembly location: " + rootPath); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Common.dll")); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPathSE, "OpenSim.Region.ScriptEngine.DotNetEngine.dll")); + + //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment"); + parameters.GenerateExecutable = false; + parameters.OutputAssembly = OutFile; + parameters.IncludeDebugInformation = CompileWithDebugInformation; + //parameters.WarningLevel = 1; // Should be 4? + parameters.TreatWarningsAsErrors = false; + + CompilerResults results; + switch (lang) + { + case enumCompileType.vb: + results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + case enumCompileType.cs: + results = CScodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + case enumCompileType.js: + results = JScodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + default: + throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\""); + } + + // Check result + // Go through errors + + // + // WARNINGS AND ERRORS + // + if (results.Errors.Count > 0) + { + string errtext = String.Empty; + foreach (CompilerError CompErr in results.Errors) + { + errtext += "Line number " + (CompErr.Line - LinesToRemoveOnError) + + ", Error Number: " + CompErr.ErrorNumber + + ", '" + CompErr.ErrorText + "'\r\n"; + } + if (!File.Exists(OutFile)) + { + throw new Exception(errtext); + } + } + + + // + // NO ERRORS, BUT NO COMPILED FILE + // + if (!File.Exists(OutFile)) + { + string errtext = String.Empty; + errtext += "No compile error. But not able to locate compiled file."; + throw new Exception(errtext); + } + return OutFile; + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs index c7fe75407d..87516da4f8 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL2CSConverter.cs @@ -1,327 +1,311 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System.Collections.Generic; -using System.Text.RegularExpressions; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL -{ - public class LSL2CSConverter - { - - - // Uses regex to convert LSL code to C# code. - - //private Regex rnw = new Regex(@"[a-zA-Z0-9_\-]", RegexOptions.Compiled); - private Dictionary dataTypes = new Dictionary(); - private Dictionary quotes = new Dictionary(); - - public LSL2CSConverter() - { - // Only the types we need to convert - dataTypes.Add("void", "void"); - dataTypes.Add("integer", "int"); - dataTypes.Add("float", "double"); - dataTypes.Add("string", "string"); - dataTypes.Add("key", "string"); - dataTypes.Add("vector", "LSL_Types.Vector3"); - dataTypes.Add("rotation", "LSL_Types.Quaternion"); - dataTypes.Add("list", "LSL_Types.list"); - dataTypes.Add("null", "null"); - } - - public string Convert(string Script) - { - quotes.Clear(); - string Return = ""; - Script = " \r\n" + Script; - - // - // Prepare script for processing - // - - // Clean up linebreaks - Script = Regex.Replace(Script, @"\r\n", "\n"); - Script = Regex.Replace(Script, @"\n", "\r\n"); - - - // QUOTE REPLACEMENT - // temporarily replace quotes so we can work our magic on the script without - // always considering if we are inside our outside ""'s - string _Script = ""; - string C; - bool in_quote = false; - bool quote_replaced = false; - string quote_replacement_string = "Q_U_O_T_E_REPLACEMENT_"; - string quote = ""; - bool last_was_escape = false; - int quote_replaced_count = 0; - for (int p = 0; p < Script.Length; p++) - { - C = Script.Substring(p, 1); - while (true) - { - // found " and last was not \ so this is not an escaped \" - if (C == "\"" && last_was_escape == false) - { - // Toggle inside/outside quote - in_quote = !in_quote; - if (in_quote) - { - quote_replaced_count++; - } - else - { - if (quote == "") - { - // We didn't replace quote, probably because of empty string? - _Script += quote_replacement_string + - quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); - } - // We just left a quote - quotes.Add( - quote_replacement_string + - quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote); - quote = ""; - } - break; - } - - if (!in_quote) - { - // We are not inside a quote - quote_replaced = false; - } - else - { - // We are inside a quote - if (!quote_replaced) - { - // Replace quote - _Script += quote_replacement_string + - quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); - quote_replaced = true; - } - quote += C; - break; - } - _Script += C; - break; - } - last_was_escape = false; - if (C == @"\") - { - last_was_escape = true; - } - } - Script = _Script; - // - // END OF QUOTE REPLACEMENT - // - - - // - // PROCESS STATES - // Remove state definitions and add state names to start of each event within state - // - int ilevel = 0; - int lastlevel = 0; - string ret = ""; - string cache = ""; - bool in_state = false; - string current_statename = ""; - for (int p = 0; p < Script.Length; p++) - { - C = Script.Substring(p, 1); - while (true) - { - // inc / dec level - if (C == @"{") - ilevel++; - if (C == @"}") - ilevel--; - if (ilevel < 0) - ilevel = 0; - cache += C; - - // if level == 0, add to return - if (ilevel == 1 && lastlevel == 0) - { - // 0 => 1: Get last - Match m = - Regex.Match(cache, @"(?![a-zA-Z_]+)\s*([a-zA-Z_]+)[^a-zA-Z_\(\)]*{", - RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - - in_state = false; - if (m.Success) - { - // Go back to level 0, this is not a state - in_state = true; - current_statename = m.Groups[1].Captures[0].Value; - //Console.WriteLine("Current statename: " + current_statename); - cache = - Regex.Replace(cache, - @"(?(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?[^a-zA-Z_\(\)]*){", - "${s1}${s2}", - RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - } - ret += cache; - cache = ""; - } - if (ilevel == 0 && lastlevel == 1) - { - // 1 => 0: Remove last } - if (in_state == true) - { - cache = cache.Remove(cache.Length - 1, 1); - //cache = Regex.Replace(cache, "}$", "", RegexOptions.Multiline | RegexOptions.Singleline); - - //Replace function names - // void dataserver(key query_id, string data) { - //cache = Regex.Replace(cache, @"([^a-zA-Z_]\s*)((?!if|switch|for)[a-zA-Z_]+\s*\([^\)]*\)[^{]*{)", "$1" + "" + "$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - //Console.WriteLine("Replacing using statename: " + current_statename); - cache = - Regex.Replace(cache, - @"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", - @"$1public " + current_statename + "_event_$2", - RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - } - - ret += cache; - cache = ""; - in_state = true; - current_statename = ""; - } - - break; - } - lastlevel = ilevel; - } - ret += cache; - cache = ""; - - Script = ret; - ret = ""; - - - foreach (string key in dataTypes.Keys) - { - string val; - dataTypes.TryGetValue(key, out val); - - // Replace CAST - (integer) with (int) - Script = - Regex.Replace(Script, @"\(" + key + @"\)", @"(" + val + ")", - RegexOptions.Compiled | RegexOptions.Multiline); - // Replace return types and function variables - integer a() and f(integer a, integer a) - Script = - Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3", - RegexOptions.Compiled | RegexOptions.Multiline); - Script = - Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,", - RegexOptions.Compiled | RegexOptions.Multiline); - } - - // Add "void" in front of functions that needs it - Script = - Regex.Replace(Script, - @"^(\s*public\s+)((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", - @"$1void $2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - - // Replace and - Script = - Regex.Replace(Script, @"<([^,>;\)]*,[^,>;\)]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Quaternion($1)", - RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - Script = - Regex.Replace(Script, @"<([^,>;\)]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Vector3($1)", - RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - - // Replace List []'s - Script = - Regex.Replace(Script, @"\[([^\]]*)\]", @"new LSL_Types.list($1)", - RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - - - // Replace (string) to .ToString() // - Script = - Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_]+(\s*\([^\)]*\))?)", @"$1.ToString()", - RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - Script = - Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_]+(\s*\([^\)]*\))?)", @"$1.Parse($2)", - RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); - - - // REPLACE BACK QUOTES - foreach (string key in quotes.Keys) - { - string val; - quotes.TryGetValue(key, out val); - Script = Script.Replace(key, "\"" + val + "\""); - } - - - // Add namespace, class name and inheritance - - Return = "" + - "using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;"; - //"using System; " + - //"using System.Collections.Generic; " + - //"using System.Text; " + - //"using OpenSim.Region.ScriptEngine.Common; " + - //"using integer = System.Int32; " + - //"using key = System.String; "; - - //// Make a Using out of DataTypes - //// Using integer = System.Int32; - //string _val; - //foreach (string key in DataTypes.Keys) - //{ - // DataTypes.TryGetValue(key, out _val); - // if (key != _val) - // { - // Return += "using " + key + " = " + _val + "; "; - // } - //} - - - Return += "" + - "namespace SecondLife { "; - Return += "" + - //"[Serializable] " + - "public class Script : OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass { "; - Return += @"public Script() { } "; - Return += Script; - Return += "} }\r\n"; - - - quotes.Clear(); - - return Return; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public class LSL2CSConverter + { + + + // Uses regex to convert LSL code to C# code. + + //private Regex rnw = new Regex(@"[a-zA-Z0-9_\-]", RegexOptions.Compiled); + private Dictionary dataTypes = new Dictionary(); + private Dictionary quotes = new Dictionary(); + + public LSL2CSConverter() + { + // Only the types we need to convert + dataTypes.Add("void", "void"); + dataTypes.Add("integer", "int"); + dataTypes.Add("float", "double"); + dataTypes.Add("string", "string"); + dataTypes.Add("key", "string"); + dataTypes.Add("vector", "LSL_Types.Vector3"); + dataTypes.Add("rotation", "LSL_Types.Quaternion"); + dataTypes.Add("list", "LSL_Types.list"); + dataTypes.Add("null", "null"); + } + + public string Convert(string Script) + { + quotes.Clear(); + string Return = System.String.Empty; + Script = " \r\n" + Script; + + // + // Prepare script for processing + // + + // Clean up linebreaks + Script = Regex.Replace(Script, @"\r\n", "\n"); + Script = Regex.Replace(Script, @"\n", "\r\n"); + + + // QUOTE REPLACEMENT + // temporarily replace quotes so we can work our magic on the script without + // always considering if we are inside our outside quotes's + // TODO: Does this work on half-quotes in strings? ;) + string _Script = System.String.Empty; + string C; + bool in_quote = false; + bool quote_replaced = false; + string quote_replacement_string = "Q_U_O_T_E_REPLACEMENT_"; + string quote = System.String.Empty; + bool last_was_escape = false; + int quote_replaced_count = 0; + for (int p = 0; p < Script.Length; p++) + { + C = Script.Substring(p, 1); + while (true) + { + // found " and last was not \ so this is not an escaped \" + if (C == "\"" && last_was_escape == false) + { + // Toggle inside/outside quote + in_quote = !in_quote; + if (in_quote) + { + quote_replaced_count++; + } + else + { + if (quote == System.String.Empty) + { + // We didn't replace quote, probably because of empty string? + _Script += quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); + } + // We just left a quote + quotes.Add( + quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote); + quote = System.String.Empty; + } + break; + } + + if (!in_quote) + { + // We are not inside a quote + quote_replaced = false; + } + else + { + // We are inside a quote + if (!quote_replaced) + { + // Replace quote + _Script += quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); + quote_replaced = true; + } + quote += C; + break; + } + _Script += C; + break; + } + last_was_escape = false; + if (C == @"\") + { + last_was_escape = true; + } + } + Script = _Script; + // + // END OF QUOTE REPLACEMENT + // + + + // + // PROCESS STATES + // Remove state definitions and add state names to start of each event within state + // + int ilevel = 0; + int lastlevel = 0; + string ret = System.String.Empty; + string cache = System.String.Empty; + bool in_state = false; + string current_statename = System.String.Empty; + for (int p = 0; p < Script.Length; p++) + { + C = Script.Substring(p, 1); + while (true) + { + // inc / dec level + if (C == @"{") + ilevel++; + if (C == @"}") + ilevel--; + if (ilevel < 0) + ilevel = 0; + cache += C; + + // if level == 0, add to return + if (ilevel == 1 && lastlevel == 0) + { + // 0 => 1: Get last + Match m = + Regex.Match(cache, @"(?![a-zA-Z_]+)\s*([a-zA-Z_]+)[^a-zA-Z_\(\)]*{", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + in_state = false; + if (m.Success) + { + // Go back to level 0, this is not a state + in_state = true; + current_statename = m.Groups[1].Captures[0].Value; + //Console.WriteLine("Current statename: " + current_statename); + cache = + Regex.Replace(cache, + @"(?(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?[^a-zA-Z_\(\)]*){", + "${s1}${s2}", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + } + ret += cache; + cache = String.Empty; + } + if (ilevel == 0 && lastlevel == 1) + { + // 1 => 0: Remove last } + if (in_state == true) + { + cache = cache.Remove(cache.Length - 1, 1); + //cache = Regex.Replace(cache, "}$", String.Empty, RegexOptions.Multiline | RegexOptions.Singleline); + + //Replace function names + // void dataserver(key query_id, string data) { + //cache = Regex.Replace(cache, @"([^a-zA-Z_]\s*)((?!if|switch|for)[a-zA-Z_]+\s*\([^\)]*\)[^{]*{)", "$1" + "" + "$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + //Console.WriteLine("Replacing using statename: " + current_statename); + cache = + Regex.Replace(cache, + @"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"$1public " + current_statename + "_event_$2", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + } + + ret += cache; + cache = String.Empty; + in_state = true; + current_statename = String.Empty; + } + + break; + } + lastlevel = ilevel; + } + ret += cache; + cache = String.Empty; + + Script = ret; + ret = String.Empty; + + + foreach (string key in dataTypes.Keys) + { + string val; + dataTypes.TryGetValue(key, out val); + + // Replace CAST - (integer) with (int) + Script = + Regex.Replace(Script, @"\(" + key + @"\)", @"(" + val + ")", + RegexOptions.Compiled | RegexOptions.Multiline); + // Replace return types and function variables - integer a() and f(integer a, integer a) + Script = + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3", + RegexOptions.Compiled | RegexOptions.Multiline); + Script = + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,", + RegexOptions.Compiled | RegexOptions.Multiline); + } + + // Add "void" in front of functions that needs it + Script = + Regex.Replace(Script, + @"^(\s*public\s+)?((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"$1void $2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace and + Script = + Regex.Replace(Script, @"<([^,>;]*,[^,>;\)]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Quaternion($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + Script = + Regex.Replace(Script, @"<([^,>;]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Vector3($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace List []'s + Script = + Regex.Replace(Script, @"\[([^\]]*)\]", @"new LSL_Types.list($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + + // Replace (string) to .ToString() // + Script = + Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.ToString()", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + Script = + Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.Parse($2)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + + // REPLACE BACK QUOTES + foreach (string key in quotes.Keys) + { + string val; + quotes.TryGetValue(key, out val); + Script = Script.Replace(key, "\"" + val + "\""); + } + + + // Add namespace, class name and inheritance + + Return = String.Empty;// + + //"using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;"; + + + //Return += String.Empty + + // "namespace SecondLife { "; + //Return += String.Empty + + // //"[Serializable] " + + // "public class Script : OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { "; + //Return += @"public Script() { } "; + Return += Script; + //Return += "} }\r\n"; + + + quotes.Clear(); + + return Return; + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs deleted file mode 100644 index f5139b782a..0000000000 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs +++ /dev/null @@ -1,364 +0,0 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; -using libsecondlife; -using OpenSim.Framework; -using OpenSim.Region.Environment.Scenes.Scripting; -using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine -{ - /// - /// EventQueueManager handles event queues - /// Events are queued and executed in separate thread - /// - [Serializable] - internal class EventQueueManager - { - - // - // Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine". - // - // Class purpose is to queue and execute functions that are received by "EventManager": - // - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution. - // - allowing us to prioritize and control execution of script functions. - // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety. - // - // 1. Hold an execution queue for scripts - // 2. Use threads to process queue, each thread executes one script function on each pass. - // 3. Catch any script error and process it - // - // - // Notes: - // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts. - // Not noticeable unless server is under high load. - // * This class contains the number of threads used for script executions. Since we are not microthreading scripts yet, - // increase number of threads to allow more concurrent script executions in OpenSim. - // - - - /// - /// List of threads processing event queue - /// - private List eventQueueThreads = new List(); - - private object queueLock = new object(); // Mutex lock object - - /// - /// How many ms to sleep if queue is empty - /// - private int nothingToDoSleepms = 50; - - /// - /// How many threads to process queue with - /// - private int numberOfThreads = 2; - - /// - /// Queue containing events waiting to be executed - /// - private Queue eventQueue = new Queue(); - - /// - /// Queue item structure - /// - private struct QueueItemStruct - { - public uint localID; - public LLUUID itemID; - public string functionName; - public object[] param; - } - - /// - /// List of localID locks for mutex processing of script events - /// - private List objectLocks = new List(); - - private object tryLockLock = new object(); // Mutex lock object - - private ScriptEngine m_ScriptEngine; - - public EventQueueManager(ScriptEngine _ScriptEngine) - { - m_ScriptEngine = _ScriptEngine; - - // - // Start event queue processing threads (worker threads) - // - for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++) - { - Thread EventQueueThread = new Thread(EventQueueThreadLoop); - eventQueueThreads.Add(EventQueueThread); - EventQueueThread.IsBackground = true; - EventQueueThread.Priority = ThreadPriority.BelowNormal; - EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; - EventQueueThread.Start(); - } - } - - ~EventQueueManager() - { - // Kill worker threads - foreach (Thread EventQueueThread in new ArrayList(eventQueueThreads)) - { - if (EventQueueThread != null && EventQueueThread.IsAlive == true) - { - try - { - EventQueueThread.Abort(); - EventQueueThread.Join(); - } - catch (Exception) - { - //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString()); - } - } - } - eventQueueThreads.Clear(); - // Todo: Clean up our queues - eventQueue.Clear(); - } - - /// - /// Queue processing thread loop - /// - private void EventQueueThreadLoop() - { - //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned"); - try - { - QueueItemStruct BlankQIS = new QueueItemStruct(); - while (true) - { - try - { - QueueItemStruct QIS = BlankQIS; - bool GotItem = false; - - if (eventQueue.Count == 0) - { - // Nothing to do? Sleep a bit waiting for something to do - Thread.Sleep(nothingToDoSleepms); - } - else - { - // Something in queue, process - //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); - - // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD - lock (queueLock) - { - GotItem = false; - for (int qc = 0; qc < eventQueue.Count; qc++) - { - // Get queue item - QIS = eventQueue.Dequeue(); - - // Check if object is being processed by someone else - if (TryLock(QIS.localID) == false) - { - // Object is already being processed, requeue it - eventQueue.Enqueue(QIS); - } - else - { - // We have lock on an object and can process it - GotItem = true; - break; - } - } // go through queue - } // lock - - if (GotItem == true) - { - // Execute function - try - { -#if DEBUG - m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n" - + "QIS.localID: " + QIS.localID - + ", QIS.itemID: " + QIS.itemID - + ", QIS.functionName: " + QIS.functionName); -#endif - m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID, - QIS.functionName, QIS.param); - } - catch (Exception e) - { - // DISPLAY ERROR INWORLD - string text = "Error executing script function \"" + QIS.functionName + "\":\r\n"; - //if (e.InnerException != null) - //{ - // Send inner exception - text += e.InnerException.Message.ToString(); - //} - //else - //{ - text += "\r\n"; - // Send normal - text += e.Message.ToString(); - //} - try - { - if (text.Length > 1500) - text = text.Substring(0, 1500); - IScriptHost m_host = m_ScriptEngine.World.GetSceneObjectPart(QIS.localID); - //if (m_host != null) - //{ - m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, - m_host.AbsolutePosition, m_host.Name, m_host.UUID); - } - catch - { - //} - //else - //{ - // T oconsole - m_ScriptEngine.Log.Error("ScriptEngine", - "Unable to send text in-world:\r\n" + text); - } - } - finally - { - ReleaseLock(QIS.localID); - } - } - } // Something in queue - } - catch (ThreadAbortException tae) - { - throw tae; - } - catch (Exception e) - { - m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString()); - } - } // while - } // try - catch (ThreadAbortException) - { - //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message); - } - } - - /// - /// Try to get a mutex lock on localID - /// - /// - /// - private bool TryLock(uint localID) - { - lock (tryLockLock) - { - if (objectLocks.Contains(localID) == true) - { - return false; - } - else - { - objectLocks.Add(localID); - return true; - } - } - } - - /// - /// Release mutex lock on localID - /// - /// - private void ReleaseLock(uint localID) - { - lock (tryLockLock) - { - if (objectLocks.Contains(localID) == true) - { - objectLocks.Remove(localID); - } - } - } - - - /// - /// Add event to event execution queue - /// - /// - /// Name of the function, will be state + "_event_" + FunctionName - /// Array of parameters to match event mask - public void AddToObjectQueue(uint localID, string FunctionName, object[] param) - { - // Determine all scripts in Object and add to their queue - //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName); - - - // Do we have any scripts in this object at all? If not, return - if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false) - { - //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID."); - return; - } - - Dictionary.KeyCollection scriptKeys = - m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID); - - foreach (LLUUID itemID in scriptKeys) - { - // Add to each script in that object - // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? - AddToScriptQueue(localID, itemID, FunctionName, param); - } - } - - /// - /// Add event to event execution queue - /// - /// - /// - /// Name of the function, will be state + "_event_" + FunctionName - /// Array of parameters to match event mask - public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, object[] param) - { - lock (queueLock) - { - // Create a structure and add data - QueueItemStruct QIS = new QueueItemStruct(); - QIS.localID = localID; - QIS.itemID = itemID; - QIS.functionName = FunctionName; - QIS.param = param; - - // Add it to queue - eventQueue.Enqueue(QIS); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs deleted file mode 100644 index ba8eb7af09..0000000000 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs +++ /dev/null @@ -1,287 +0,0 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.Threading; -using libsecondlife; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Modules; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine -{ - /// - /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc. - /// - internal class LSLLongCmdHandler - { - private Thread cmdHandlerThread; - private int cmdHandlerThreadCycleSleepms = 100; - - private ScriptEngine m_ScriptEngine; - - public LSLLongCmdHandler(ScriptEngine _ScriptEngine) - { - m_ScriptEngine = _ScriptEngine; - - // Start the thread that will be doing the work - cmdHandlerThread = new Thread(CmdHandlerThreadLoop); - cmdHandlerThread.Name = "CmdHandlerThread"; - cmdHandlerThread.Priority = ThreadPriority.BelowNormal; - cmdHandlerThread.IsBackground = true; - cmdHandlerThread.Start(); - } - - ~LSLLongCmdHandler() - { - // Shut down thread - try - { - if (cmdHandlerThread != null) - { - if (cmdHandlerThread.IsAlive == true) - { - cmdHandlerThread.Abort(); - cmdHandlerThread.Join(); - } - } - } - catch - { - } - } - - private void CmdHandlerThreadLoop() - { - while (true) - { - // Check timers - CheckTimerEvents(); - Thread.Sleep(25); - // Check HttpRequests - CheckHttpRequests(); - Thread.Sleep(25); - // Check XMLRPCRequests - CheckXMLRPCRequests(); - Thread.Sleep(25); - // Check Listeners - CheckListeners(); - Thread.Sleep(25); - - // Sleep before next cycle - //Thread.Sleep(cmdHandlerThreadCycleSleepms); - } - } - - /// - /// Remove a specific script (and all its pending commands) - /// - /// - /// - public void RemoveScript(uint localID, LLUUID itemID) - { - // Remove a specific script - - // Remove from: Timers - UnSetTimerEvents(localID, itemID); - // Remove from: HttpRequest - IHttpRequests iHttpReq = - m_ScriptEngine.World.RequestModuleInterface(); - iHttpReq.StopHttpRequest(localID, itemID); - } - - #region TIMER - - // - // TIMER - // - private class TimerClass - { - public uint localID; - public LLUUID itemID; - public double interval; - public DateTime next; - } - - private List Timers = new List(); - private object TimerListLock = new object(); - - public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec) - { - Console.WriteLine("SetTimerEvent"); - - // Always remove first, in case this is a re-set - UnSetTimerEvents(m_localID, m_itemID); - if (sec == 0) // Disabling timer - return; - - // Add to timer - TimerClass ts = new TimerClass(); - ts.localID = m_localID; - ts.itemID = m_itemID; - ts.interval = sec; - ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); - lock (TimerListLock) - { - Timers.Add(ts); - } - } - - public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID) - { - // Remove from timer - lock (TimerListLock) - { - List NewTimers = new List(); - foreach (TimerClass ts in Timers) - { - if (ts.localID != m_localID && ts.itemID != m_itemID) - { - NewTimers.Add(ts); - } - } - Timers.Clear(); - Timers = NewTimers; - } - } - - public void CheckTimerEvents() - { - // Nothing to do here? - if (Timers.Count == 0) - return; - - lock (TimerListLock) - { - // Go through all timers - foreach (TimerClass ts in Timers) - { - // Time has passed? - if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) - { - // Add it to queue - m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", - new object[] {}); - // set next interval - - - ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); - } - } - } // lock - } - - #endregion - - #region HTTP REQUEST - - public void CheckHttpRequests() - { - IHttpRequests iHttpReq = - m_ScriptEngine.World.RequestModuleInterface(); - - HttpRequestClass httpInfo = null; - - if (iHttpReq != null) - httpInfo = iHttpReq.GetNextCompletedRequest(); - - while (httpInfo != null) - { - //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status); - - // Deliver data to prim's remote_data handler - // - // TODO: Returning null for metadata, since the lsl function - // only returns the byte for HTTP_BODY_TRUNCATED, which is not - // implemented here yet anyway. Should be fixed if/when maxsize - // is supported - - object[] resobj = new object[] - { - httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body - }; - - m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( - httpInfo.localID, httpInfo.itemID, "http_response", resobj - ); - - httpInfo.Stop(); - httpInfo = null; - - httpInfo = iHttpReq.GetNextCompletedRequest(); - } - } - - #endregion - - public void CheckXMLRPCRequests() - { - IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface(); - - if (xmlrpc != null) - { - while (xmlrpc.hasRequests()) - { - RPCRequestInfo rInfo = xmlrpc.GetNextRequest(); - //Console.WriteLine("PICKED REQUEST"); - - //Deliver data to prim's remote_data handler - object[] resobj = new object[] - { - 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), "", - rInfo.GetIntValue(), - rInfo.GetStrVal() - }; - m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( - rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", resobj - ); - } - } - } - - public void CheckListeners() - { - IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface(); - - while (comms.HasMessages()) - { - ListenerInfo lInfo = comms.GetNextMessage(); - - //Deliver data to prim's listen handler - object[] resobj = new object[] - { - lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() - }; - - m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( - lInfo.GetLocalID(), lInfo.GetItemID(), "listen", resobj - ); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs index ab34b15ba6..b7d705b8c7 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs @@ -1,38 +1,66 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly : AssemblyTitle("OpenSim.Region.ScriptEngine.DotNetEngine")] -[assembly : AssemblyDescription("")] -[assembly : AssemblyConfiguration("")] -[assembly : AssemblyCompany("")] -[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.DotNetEngine")] -[assembly : AssemblyCopyright("Copyright © 2007")] -[assembly : AssemblyTrademark("")] -[assembly : AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly : ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly : Guid("2842257e-6fde-4460-9368-4cde57fa9cc4")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly : AssemblyVersion("1.0.0.0")] -[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly : AssemblyTitle("OpenSim.Region.ScriptEngine.DotNetEngine")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.DotNetEngine")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2008")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly : ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly : Guid("2842257e-6fde-4460-9368-4cde57fa9cc4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs index 134a2ab179..afe472a0d6 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs @@ -1,118 +1,56 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -using System; -using Nini.Config; -using OpenSim.Framework.Console; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine -{ - /// - /// This is the root object for ScriptEngine. Objects access each other trough this class. - /// - /// - [Serializable] - public class ScriptEngine : IRegionModule - { - public Scene World; - public EventManager m_EventManager; // Handles and queues incoming events from OpenSim - internal EventQueueManager m_EventQueueManager; // Executes events - public ScriptManager m_ScriptManager; // Load, unload and execute scripts - internal AppDomainManager m_AppDomainManager; - internal LSLLongCmdHandler m_LSLLongCmdHandler; - - private LogBase m_log; - - public ScriptEngine() - { - //Common.SendToDebug("ScriptEngine Object Initialized"); - Common.mySE = this; - } - - public LogBase Log - { - get { return m_log; } - } - - public void InitializeEngine(Scene Sceneworld, LogBase logger) - { - World = Sceneworld; - m_log = logger; - - Log.Verbose("ScriptEngine", "DotNet & LSL ScriptEngine initializing"); - - //m_logger.Status("ScriptEngine", "InitializeEngine"); - - // Create all objects we'll be using - m_EventQueueManager = new EventQueueManager(this); - m_EventManager = new EventManager(this); - m_ScriptManager = new ScriptManager(this); - m_AppDomainManager = new AppDomainManager(); - m_LSLLongCmdHandler = new LSLLongCmdHandler(this); - - // Should we iterate the region for scripts that needs starting? - // Or can we assume we are loaded before anything else so we can use proper events? - } - - public void Shutdown() - { - // We are shutting down - } - - - - #region IRegionModule - - public void Initialise(Scene scene, IConfigSource config) - { - InitializeEngine(scene, MainLog.Instance); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "DotNetEngine"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + [Serializable] + public class ScriptEngine : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptEngine + { + // We need to override a few things for our DotNetEngine + public override void Initialise(Scene scene, IConfigSource config) + { + ConfigSource = config; + InitializeEngine(scene, config, true, GetScriptManager()); + } + + public override OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager _GetScriptManager() + { + return new ScriptManager(this); + } + + public override string ScriptEngineName + { + get { return "ScriptEngine.DotNetEngine"; } + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs index 07fcfa66bd..68ac99cc5e 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs @@ -1,455 +1,164 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Runtime.Serialization.Formatters.Binary; -using System.Threading; -using libsecondlife; -using OpenSim.Framework; -using OpenSim.Region.Environment.Scenes; -using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler; -using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine -{ - /// - /// Loads scripts - /// Compiles them if necessary - /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution) - /// - /// - - // This class is as close as you get to the script without being inside script class. It handles all the dirty work for other classes. - // * Keeps track of running scripts - // * Compiles script if necessary (through "Compiler") - // * Loads script (through "AppDomainManager" called from for example "EventQueueManager") - // * Executes functions inside script (called from for example "EventQueueManager" class) - // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager") - // * Dedicated load/unload thread, and queues loading/unloading. - // This so that scripts starting or stopping will not slow down other theads or whole system. - // - [Serializable] - public class ScriptManager - { - #region Declares - - private Thread scriptLoadUnloadThread; - private int scriptLoadUnloadThread_IdleSleepms = 100; - private Queue LUQueue = new Queue(); - - - // Load/Unload structure - private struct LUStruct - { - public uint localID; - public LLUUID itemID; - public string script; - public LUType Action; - } - - private enum LUType - { - Unknown = 0, - Load = 1, - Unload = 2 - } - - // Object> - // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. - // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! - internal Dictionary> Scripts = - new Dictionary>(); - - public Scene World - { - get { return m_scriptEngine.World; } - } - - #endregion - - #region Object init/shutdown - - private ScriptEngine m_scriptEngine; - - public ScriptManager(ScriptEngine scriptEngine) - { - m_scriptEngine = scriptEngine; - AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); - scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop); - scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread"; - scriptLoadUnloadThread.IsBackground = true; - scriptLoadUnloadThread.Priority = ThreadPriority.BelowNormal; - scriptLoadUnloadThread.Start(); - } - - ~ScriptManager() - { - // Abort load/unload thread - try - { - if (scriptLoadUnloadThread != null) - { - if (scriptLoadUnloadThread.IsAlive == true) - { - scriptLoadUnloadThread.Abort(); - scriptLoadUnloadThread.Join(); - } - } - } - catch - { - } - } - - #endregion - - #region Load / Unload scripts (Thread loop) - - private void ScriptLoadUnloadThreadLoop() - { - try - { - while (true) - { - if (LUQueue.Count == 0) - Thread.Sleep(scriptLoadUnloadThread_IdleSleepms); - if (LUQueue.Count > 0) - { - LUStruct item = LUQueue.Dequeue(); - if (item.Action == LUType.Unload) - _StopScript(item.localID, item.itemID); - if (item.Action == LUType.Load) - _StartScript(item.localID, item.itemID, item.script); - } - } - } - catch (ThreadAbortException tae) - { - string a = tae.ToString(); - a = ""; - // Expected - } - } - - #endregion - - #region Helper functions - - private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) - { - //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name); - return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null; - } - - #endregion - - #region Internal functions to keep track of script - - internal Dictionary.KeyCollection GetScriptKeys(uint localID) - { - if (Scripts.ContainsKey(localID) == false) - return null; - - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - - return Obj.Keys; - } - - internal LSL_BaseClass GetScript(uint localID, LLUUID itemID) - { - if (Scripts.ContainsKey(localID) == false) - return null; - - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - if (Obj.ContainsKey(itemID) == false) - return null; - - // Get script - LSL_BaseClass Script; - Obj.TryGetValue(itemID, out Script); - - return Script; - } - - internal void SetScript(uint localID, LLUUID itemID, LSL_BaseClass Script) - { - // Create object if it doesn't exist - if (Scripts.ContainsKey(localID) == false) - { - Scripts.Add(localID, new Dictionary()); - } - - // Delete script if it exists - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - if (Obj.ContainsKey(itemID) == true) - Obj.Remove(itemID); - - // Add to object - Obj.Add(itemID, Script); - } - - internal void RemoveScript(uint localID, LLUUID itemID) - { - // Don't have that object? - if (Scripts.ContainsKey(localID) == false) - return; - - // Delete script if it exists - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - if (Obj.ContainsKey(itemID) == true) - Obj.Remove(itemID); - } - - #endregion - - #region Start/Stop/Reset script - - private Object startStopLock = new Object(); - - /// - /// Fetches, loads and hooks up a script to an objects events - /// - /// - /// - public void StartScript(uint localID, LLUUID itemID, string Script) - { - LUStruct ls = new LUStruct(); - ls.localID = localID; - ls.itemID = itemID; - ls.script = Script; - ls.Action = LUType.Load; - LUQueue.Enqueue(ls); - } - - /// - /// Disables and unloads a script - /// - /// - /// - public void StopScript(uint localID, LLUUID itemID) - { - LUStruct ls = new LUStruct(); - ls.localID = localID; - ls.itemID = itemID; - ls.Action = LUType.Unload; - LUQueue.Enqueue(ls); - } - - public void ResetScript(uint localID, LLUUID itemID) - { - string script = GetScript(localID, itemID).SourceCode; - StopScript(localID, itemID); - StartScript(localID, itemID, script); - } - - // Create a new instance of the compiler (reuse) - private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler(); - - private void _StartScript(uint localID, LLUUID itemID, string Script) - { - lock (startStopLock) - { - //IScriptHost root = host.GetRoot(); - Console.WriteLine("ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID); - - // We will initialize and start the script. - // It will be up to the script itself to hook up the correct events. - string ScriptSource = ""; - - SceneObjectPart m_host = World.GetSceneObjectPart(localID); - - try - { - if (!Script.EndsWith("dll")) - { - // Compile (We assume LSL) - ScriptSource = LSLCompiler.CompileFromLSLText(Script); - //Console.WriteLine("Compilation of " + FileName + " done"); - // * Insert yield into code - ScriptSource = ProcessYield(ScriptSource); - } - else - { - ScriptSource = Script; - } - -#if DEBUG - long before; - before = GC.GetTotalMemory(true); -#endif - - LSL_BaseClass CompiledScript; - CompiledScript = m_scriptEngine.m_AppDomainManager.LoadScript(ScriptSource); - -#if DEBUG - Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before); -#endif - - CompiledScript.SourceCode = ScriptSource; - // Add it to our script memstruct - SetScript(localID, itemID, CompiledScript); - - // We need to give (untrusted) assembly a private instance of BuiltIns - // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. - - - LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(m_scriptEngine, m_host, localID, itemID); - - // Start the script - giving it BuiltIns - CompiledScript.Start(LSLB); - - // Fire the first start-event - m_scriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_entry", new object[] {}); - } - catch (Exception e) - { - //m_scriptEngine.Log.Error("ScriptEngine", "Error compiling script: " + e.ToString()); - try - { - // DISPLAY ERROR INWORLD - string text = "Error compiling script:\r\n" + e.Message.ToString(); - if (text.Length > 1500) - text = text.Substring(0, 1500); - World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, - m_host.Name, m_host.UUID); - } - catch (Exception e2) - { - m_scriptEngine.Log.Error("ScriptEngine", "Error displaying error in-world: " + e2.ToString()); - m_scriptEngine.Log.Error("ScriptEngine", - "Errormessage: Error compiling script:\r\n" + e.Message.ToString()); - } - } - } - } - - private void _StopScript(uint localID, LLUUID itemID) - { - lock (startStopLock) - { - // Stop script - Console.WriteLine("Stop script localID: " + localID + " LLUID: " + itemID.ToString()); - - - // Stop long command on script - m_scriptEngine.m_LSLLongCmdHandler.RemoveScript(localID, itemID); - - LSL_BaseClass LSLBC = GetScript(localID, itemID); - if (LSLBC == null) - return; - - // TEMP: First serialize it - //GetSerializedScript(localID, itemID); - - - try - { - // Get AppDomain - AppDomain ad = LSLBC.Exec.GetAppDomain(); - // Tell script not to accept new requests - GetScript(localID, itemID).Exec.StopScript(); - // Remove from internal structure - RemoveScript(localID, itemID); - // Tell AppDomain that we have stopped script - m_scriptEngine.m_AppDomainManager.StopScript(ad); - } - catch (Exception e) - { - Console.WriteLine("Exception stopping script localID: " + localID + " LLUID: " + itemID.ToString() + - ": " + e.ToString()); - } - } - } - - private string ProcessYield(string FileName) - { - // TODO: Create a new assembly and copy old but insert Yield Code - //return TempDotNetMicroThreadingCodeInjector.TestFix(FileName); - return FileName; - } - - #endregion - - #region Perform event execution in script - - /// - /// Execute a LL-event-function in Script - /// - /// Object the script is located in - /// Script ID - /// Name of function - /// Arguments to pass to function - internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, object[] args) - { -#if DEBUG - Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName); -#endif - // Execute a function in the script - //m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); - LSL_BaseClass Script = m_scriptEngine.m_ScriptManager.GetScript(localID, itemID); - if (Script == null) - return; - -#if DEBUG - Console.WriteLine("ScriptEngine: Executing event: " + FunctionName); -#endif - // Must be done in correct AppDomain, so leaving it up to the script itself - Script.Exec.ExecuteEvent(FunctionName, args); - } - - #endregion - - #region Script serialization/deserialization - - public void GetSerializedScript(uint localID, LLUUID itemID) - { - // Serialize the script and return it - // Should not be a problem - FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID); - BinaryFormatter b = new BinaryFormatter(); - b.Serialize(fs, GetScript(localID, itemID)); - fs.Close(); - } - - public void PutSerializedScript(uint localID, LLUUID itemID) - { - // Deserialize the script and inject it into an AppDomain - - // How to inject into an AppDomain? - } - - #endregion - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + public class ScriptManager : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager + { + public ScriptManager(Common.ScriptEngineBase.ScriptEngine scriptEngine) + : base(scriptEngine) + { + base.m_scriptEngine = scriptEngine; + } + private Compiler.LSL.Compiler LSLCompiler; + + + public override void Initialize() + { + // Create our compiler + LSLCompiler = new Compiler.LSL.Compiler(m_scriptEngine); + } + + // KEEP TRACK OF SCRIPTS + //internal Dictionary> Scripts = new Dictionary>(); + // LOAD SCRIPT + // UNLOAD SCRIPT + // PROVIDE SCRIPT WITH ITS INTERFACE TO OpenSim + + + public override void _StartScript(uint localID, LLUUID itemID, string Script) + { + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID); + + + //IScriptHost root = host.GetRoot(); + + // We will initialize and start the script. + // It will be up to the script itself to hook up the correct events. + string ScriptSource = String.Empty; + + SceneObjectPart m_host = World.GetSceneObjectPart(localID); + + try + { + // Compile (We assume LSL) + ScriptSource = LSLCompiler.PerformScriptCompile(Script); + +#if DEBUG + long before; + before = GC.GetTotalMemory(true); +#endif + + IScript CompiledScript; + CompiledScript = m_scriptEngine.m_AppDomainManager.LoadScript(ScriptSource); + +#if DEBUG + m_scriptEngine.Log.DebugFormat("[" + m_scriptEngine.ScriptEngineName + "]: Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before); +#endif + + CompiledScript.Source = Script; + // Add it to our script memstruct + m_scriptEngine.m_ScriptManager.SetScript(localID, itemID, CompiledScript); + + // We need to give (untrusted) assembly a private instance of BuiltIns + // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. + + + LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(m_scriptEngine, m_host, localID, itemID); + + // Start the script - giving it BuiltIns + CompiledScript.Start(LSLB); + + // Fire the first start-event + m_scriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_entry", EventQueueManager.llDetectNull, new object[] { }); + } + catch (Exception e) // LEGIT: User Scripting + { + //m_scriptEngine.Log.Error("[ScriptEngine]: Error compiling script: " + e.ToString()); + try + { + // DISPLAY ERROR INWORLD + string text = "Error compiling script:\r\n" + e.Message.ToString(); + if (text.Length > 1500) + text = text.Substring(0, 1500); + World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, + m_host.Name, m_host.UUID); + } + catch (Exception e2) // LEGIT: User Scripting + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Error displaying error in-world: " + e2.ToString()); + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Errormessage: Error compiling script:\r\n" + e.Message.ToString()); + } + } + } + + public override void _StopScript(uint localID, LLUUID itemID) + { + // Stop script +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Stop script localID: " + localID + " LLUID: " + itemID.ToString()); +#endif + + // Stop long command on script + m_scriptEngine.m_ASYNCLSLCommandManager.RemoveScript(localID, itemID); + + IScript LSLBC = GetScript(localID, itemID); + if (LSLBC == null) + return; + + // TEMP: First serialize it + //GetSerializedScript(localID, itemID); + + try + { + // Get AppDomain + AppDomain ad = LSLBC.Exec.GetAppDomain(); + // Tell script not to accept new requests + m_scriptEngine.m_ScriptManager.GetScript(localID, itemID).Exec.StopScript(); + // Remove from internal structure + m_scriptEngine.m_ScriptManager.RemoveScript(localID, itemID); + // Tell AppDomain that we have stopped script + m_scriptEngine.m_AppDomainManager.StopScript(ad); + } + catch (Exception e) // LEGIT: User Scripting + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception stopping script localID: " + localID + " LLUID: " + itemID.ToString() + + ": " + e.ToString()); + } + } + } +} diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Common.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Common.cs new file mode 100644 index 0000000000..d1bc21d6e5 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Common.cs @@ -0,0 +1,86 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + public static class Common + { + public static bool Debug = true; + public static bool IL_UseTryCatch = true; + public static bool IL_CreateConstructor = true; + public static bool IL_CreateFunctionList = true; + public static bool IL_ProcessCodeChunks = true; + + public delegate void SendToDebugEventDelegate(string Message); + + public delegate void SendToLogEventDelegate(string Message); + + public static event SendToDebugEventDelegate SendToDebugEvent; + public static event SendToLogEventDelegate SendToLogEvent; + + public static void SendToDebug(string Message) + { + //if (Debug == true) + Console.WriteLine("COMPILER:Debug: " + Message); + SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + + public static void SendToLog(string Message) + { + //if (Debug == true) + Console.WriteLine("COMPILER:LOG: " + Message); + SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + } + + public static class IL_Helper + { + public static string ReverseFormatString(string text1, string format) + { + Common.SendToDebug("ReverseFormatString text1: " + text1); + Common.SendToDebug("ReverseFormatString format: " + format); + return string.Format(format, text1); + } + + public static string ReverseFormatString(string text1, UInt32 text2, string format) + { + Common.SendToDebug("ReverseFormatString text1: " + text1); + Common.SendToDebug("ReverseFormatString text2: " + text2.ToString()); + Common.SendToDebug("ReverseFormatString format: " + format); + return string.Format(format, text1, text2.ToString()); + } + + public static string Cast_ToString(object obj) + { + Common.SendToDebug("OBJECT TO BE CASTED: " + obj.GetType().ToString()); + return "ABCDEFGIHJKLMNOPQ123"; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Engine.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Engine.cs new file mode 100644 index 0000000000..c6fa4ce73e --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/Engine.cs @@ -0,0 +1,293 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.LSOEngine.LSO; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + public class Engine + { + //private string LSO_FileName = @"LSO\AdditionTest.lso"; + private string LSO_FileName; // = @"LSO\CloseToDefault.lso"; + private AppDomain appDomain; + + public string Compile(string LSOFileName) + { + LSO_FileName = LSOFileName; + + + //appDomain = AppDomain.CreateDomain("AlternateAppDomain"); + appDomain = Thread.GetDomain(); + + // Create Assembly Name + AssemblyName asmName = new AssemblyName(); + asmName.Name = Path.GetFileNameWithoutExtension(LSO_FileName); + //asmName.Name = "TestAssembly"; + + string DLL_FileName = asmName.Name + ".dll"; + string DLL_FileName_WithPath = Path.GetDirectoryName(LSO_FileName) + @"\" + DLL_FileName; + + LSOEngine.LSO.Common.SendToLog("LSO File Name: " + Path.GetFileName(LSO_FileName)); + LSOEngine.LSO.Common.SendToLog("Assembly name: " + asmName.Name); + LSOEngine.LSO.Common.SendToLog("Assembly File Name: " + asmName.Name + ".dll"); + LSOEngine.LSO.Common.SendToLog("Starting processing of LSL ByteCode..."); + LSOEngine.LSO.Common.SendToLog(String.Empty); + + + // Create Assembly + AssemblyBuilder asmBuilder = appDomain.DefineDynamicAssembly( + asmName, + AssemblyBuilderAccess.RunAndSave + ); + //// Create Assembly + //AssemblyBuilder asmBuilder = + // Thread.GetDomain().DefineDynamicAssembly + //(asmName, AssemblyBuilderAccess.RunAndSave); + + // Create a module (and save to disk) + ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule + (asmName.Name, + DLL_FileName); + + //Common.SendToDebug("asmName.Name is still \String.Empty + asmName.Name + "\String.Empty); + // Create a Class (/Type) + TypeBuilder typeBuilder = modBuilder.DefineType( + "LSL_ScriptObject", + TypeAttributes.Public | TypeAttributes.BeforeFieldInit, + typeof (LSL_BaseClass)); + //, + // typeof()); + //, typeof(LSL_BuiltIn_Commands_Interface)); + //, + // typeof(object), + // new Type[] { typeof(LSL_CLRInterface.LSLScript) }); + + + /* + * Generate the IL itself + */ + + LSO_Parser LSOP = new LSO_Parser(LSO_FileName, typeBuilder); + LSOP.OpenFile(); + LSOP.Parse(); + + // Constructor has to be created AFTER LSO_Parser because of accumulated variables + if (LSOEngine.LSO.Common.IL_CreateConstructor) + IL_CREATE_CONSTRUCTOR(typeBuilder, LSOP); + + LSOP.CloseFile(); + /* + * Done generating. Create a type and run it. + */ + + + LSOEngine.LSO.Common.SendToLog("Attempting to compile assembly..."); + // Compile it + Type type = typeBuilder.CreateType(); + LSOEngine.LSO.Common.SendToLog("Compilation successful!"); + + LSOEngine.LSO.Common.SendToLog("Saving assembly: " + DLL_FileName); + asmBuilder.Save(DLL_FileName); + + LSOEngine.LSO.Common.SendToLog("Returning assembly filename: " + DLL_FileName); + + + return DLL_FileName; + + + //Common.SendToLog("Creating an instance of new assembly..."); + //// Create an instance we can play with + ////LSLScript hello = (LSLScript)Activator.CreateInstance(type); + ////LSL_CLRInterface.LSLScript MyScript = (LSL_CLRInterface.LSLScript)Activator.CreateInstance(type); + //object MyScript = (object)Activator.CreateInstance(type); + + + //System.Reflection.MemberInfo[] Members = type.GetMembers(); + + //Common.SendToLog("Members of assembly " + type.ToString() + ":"); + //foreach (MemberInfo member in Members) + // Common.SendToLog(member.ToString()); + + + //// Play with it + ////MyScript.event_state_entry("Test"); + //object[] args = { null }; + ////System.Collections.Generic.List Functions = (System.Collections.Generic.List)type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null); + + //string[] ret = { }; + //if (Common.IL_CreateFunctionList) + // ret = (string[])type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null); + + //foreach (string s in ret) + //{ + // Common.SendToLog(String.Empty); + // Common.SendToLog("*** Executing LSL Server Event: " + s); + // //object test = type.GetMember(s); + // //object runner = type.InvokeMember(s, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, MyScript, args); + // //runner(); + // //objBooks_Late = type.InvokeMember(s, BindingFlags.CreateInstance, null, objApp_Late, null); + // type.InvokeMember(s, BindingFlags.InvokeMethod, null, MyScript, new object[] { "Test" }); + + //} + } + + + private static void IL_CREATE_CONSTRUCTOR(TypeBuilder typeBuilder, LSO_Parser LSOP) + { + LSOEngine.LSO.Common.SendToDebug("IL_CREATE_CONSTRUCTOR()"); + //ConstructorBuilder constructor = typeBuilder.DefineConstructor( + // MethodAttributes.Public, + // CallingConventions.Standard, + // new Type[0]); + ConstructorBuilder constructor = typeBuilder.DefineConstructor( + MethodAttributes.Public | + MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName, + CallingConventions.Standard, + new Type[0]); + + //Define the reflection ConstructorInfor for System.Object + ConstructorInfo conObj = typeof (LSL_BaseClass).GetConstructor(new Type[0]); + + //call constructor of base object + ILGenerator il = constructor.GetILGenerator(); + + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, conObj); + + + //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: UInt32 State = 0;"); + //string FieldName; + //// Create state object + //FieldName = "State"; + //FieldBuilder State_fb = typeBuilder.DefineField( + // FieldName, + // typeof(UInt32), + // FieldAttributes.Public); + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Ldc_I4, 0); + //il.Emit(OpCodes.Stfld, State_fb); + + + //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: LSL_BuiltIn_Commands_TestImplementation LSL_BuiltIns = New LSL_BuiltIn_Commands_TestImplementation();"); + ////Type objType1 = typeof(object); + //Type objType1 = typeof(LSL_BuiltIn_Commands_TestImplementation); + + //FieldName = "LSL_BuiltIns"; + //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField( + // FieldName, + // objType1, + // FieldAttributes.Public); + + ////LSL_BuiltIn_Commands_TestImplementation _ti = new LSL_BuiltIn_Commands_TestImplementation(); + //il.Emit(OpCodes.Ldarg_0); + ////il.Emit(OpCodes.Ldstr, "Test 123"); + //il.Emit(OpCodes.Newobj, objType1.GetConstructor(new Type[] { })); + //il.Emit(OpCodes.Stfld, LSL_BuiltIns_fb); + + foreach (UInt32 pos in LSOP.StaticBlocks.Keys) + { + LSO_Struct.StaticBlock sb; + LSOP.StaticBlocks.TryGetValue(pos, out sb); + + if (sb.ObjectType > 0 && sb.ObjectType < 8) + { + // We don't want void or null's + + il.Emit(OpCodes.Ldarg_0); + // Push position to stack + il.Emit(OpCodes.Ldc_I4, pos); + //il.Emit(OpCodes.Box, typeof(UInt32)); + + + Type datatype = null; + + // Push data to stack + LSOEngine.LSO.Common.SendToDebug("Adding to static (" + pos + ") type: " + + ((LSO_Enums.Variable_Type_Codes) sb.ObjectType).ToString() + " (" + sb.ObjectType + + ")"); + switch ((LSO_Enums.Variable_Type_Codes) sb.ObjectType) + { + case LSO_Enums.Variable_Type_Codes.Float: + case LSO_Enums.Variable_Type_Codes.Integer: + //UInt32 + il.Emit(OpCodes.Ldc_I4, BitConverter.ToUInt32(sb.BlockVariable, 0)); + datatype = typeof (UInt32); + il.Emit(OpCodes.Box, datatype); + break; + case LSO_Enums.Variable_Type_Codes.String: + case LSO_Enums.Variable_Type_Codes.Key: + //String + LSO_Struct.HeapBlock hb = + LSOP.GetHeap(LSOP.myHeader.HR + BitConverter.ToUInt32(sb.BlockVariable, 0) - 1); + il.Emit(OpCodes.Ldstr, Encoding.UTF8.GetString(hb.Data)); + datatype = typeof (string); + break; + case LSO_Enums.Variable_Type_Codes.Vector: + datatype = typeof (LSO_Enums.Vector); + //TODO: Not implemented + break; + case LSO_Enums.Variable_Type_Codes.Rotation: + //Object + //TODO: Not implemented + datatype = typeof (LSO_Enums.Rotation); + break; + default: + datatype = typeof (object); + break; + } + + + // Make call + il.Emit(OpCodes.Call, + typeof (LSL_BaseClass).GetMethod("AddToStatic", new Type[] {typeof (UInt32), datatype})); + } + } + + + ////il.Emit(OpCodes.Newobj, typeof(UInt32)); + //il.Emit(OpCodes.Starg_0); + //// Create LSL function library + //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField("LSL_BuiltIns", typeof(LSL_BuiltIn_Commands_Interface), FieldAttributes.Public); + //il.Emit(OpCodes.Newobj, typeof(LSL_BuiltIn_Commands_Interface)); + //il.Emit(OpCodes.Stloc_1); + + il.Emit(OpCodes.Ret); + } + + + // End of class + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/IL_common_functions.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/IL_common_functions.cs new file mode 100644 index 0000000000..9c57bcddd8 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/IL_common_functions.cs @@ -0,0 +1,51 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Reflection; +using System.Reflection.Emit; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + internal partial class LSO_Parser + { + private static TypeBuilder CreateType(ModuleBuilder modBuilder, string typeName) + { + TypeBuilder typeBuilder = modBuilder.DefineType(typeName, + TypeAttributes.Public | + TypeAttributes.Class | + TypeAttributes.AutoClass | + TypeAttributes.AnsiClass | + TypeAttributes.BeforeFieldInit | + TypeAttributes.AutoLayout, + typeof (object), + new Type[] {typeof (object)}); + return typeBuilder; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_BaseClass_OPCODES.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_BaseClass_OPCODES.cs new file mode 100644 index 0000000000..d02a4359a2 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_BaseClass_OPCODES.cs @@ -0,0 +1,395 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + //public partial class LSL_BaseClass + //{ + // /* + // * OPCODES + // * + // * These are internal "assembly" commands, + // * basic operators like "ADD", "PUSH" and "POP" + // * + // * It also contains managed stack and keeps track of internal variables, etc. + // * + // */ + + + // public void StoreToLocal(UInt32 index) + // { + // // TODO: How to determine local? + // LSOEngine.LSO.Common.SendToDebug("::StoreToLocal " + index); + // if (LocalVariables.ContainsKey(index)) + // LocalVariables.Remove(index); + // LocalVariables.Add(index, LSLStack.Peek()); + // } + + // public void StoreToGlobal(UInt32 index) + // { + // LSOEngine.LSO.Common.SendToDebug("::StoreToGlobal " + index); + // if (GlobalVariables.ContainsKey(index)) + // GlobalVariables.Remove(index); + // GlobalVariables.Add(index, LSLStack.Peek()); + // } + + // public void StoreToStatic(UInt32 index) + // { + // LSOEngine.LSO.Common.SendToDebug("::StoreToStatic " + index); + // //if (StaticVariables.ContainsKey(index)) + // // StaticVariables.Remove(index); + // StaticVariables.Add(index, LSLStack.Peek()); + // } + + // public void GetFromLocal(UInt32 index) + // { + // // TODO: How to determine local? + // LSOEngine.LSO.Common.SendToDebug("::GetFromLocal " + index); + // object ret; + // LocalVariables.TryGetValue(index, out ret); + // LSLStack.Push(ret); + // //return ret; + // } + + // public void GetFromGlobal(UInt32 index) + // { + // LSOEngine.LSO.Common.SendToDebug("::GetFromGlobal " + index); + // object ret; + // GlobalVariables.TryGetValue(index, out ret); + // LSLStack.Push(ret); + // //return ret; + // } + + // public void GetFromStatic(UInt32 index) + // { + // LSOEngine.LSO.Common.SendToDebug("::GetFromStatic " + index); + // object ret; + // StaticVariables.TryGetValue(index, out ret); + // LSOEngine.LSO.Common.SendToDebug("::GetFromStatic - ObjectType: " + ret.GetType().ToString()); + // LSLStack.Push(ret); + // //return ret; + // } + + // public object POPToStack() + // { + // LSOEngine.LSO.Common.SendToDebug("::POPToStack"); + // //return LSLStack.Pop(); + // object p = LSLStack.Pop(); + // if (p.GetType() == typeof (UInt32)) + // return (UInt32) p; + // if (p.GetType() == typeof (string)) + // return (string) p; + // if (p.GetType() == typeof (Int32)) + // return (Int32) p; + // if (p.GetType() == typeof (UInt16)) + // return (UInt16) p; + // if (p.GetType() == typeof (float)) + // return (float) p; + // if (p.GetType() == typeof (LSO_Enums.Vector)) + // return (LSO_Enums.Vector) p; + // if (p.GetType() == typeof (LSO_Enums.Rotation)) + // return (LSO_Enums.Rotation) p; + // if (p.GetType() == typeof (LSO_Enums.Key)) + // return (LSO_Enums.Key) p; + + // return p; + // } + + // //public object POPToStack(UInt32 count) + // //{ + // // // POP NUMBER FROM TOP OF STACK + // // //LSLStack.SetLength(LSLStack.Length - 4); + // // Common.SendToDebug("::POPToStack " + count); + // // if (count < 2) + // // return LSLStack.Pop(); + + // // Stack s = new Stack(); + // // for (int i = 0; i < count; i++) + // // { + // // s.Push(LSLStack.Pop); + + // // } + + // //} + + // public void POP() + // { + // // POP NUMBER FROM TOP OF STACK + // //LSLStack.SetLength(LSLStack.Length - 4); + // LSOEngine.LSO.Common.SendToDebug("::POP"); + // if (LSLStack.Count < 1) + // { + // //TODO: Temporary fix + // LSOEngine.LSO.Common.SendToDebug("ERROR: TRYING TO POP EMPTY STACK!"); + // } + // else + // { + // LSLStack.Pop(); + // } + // } + + // public void PUSH(object Param) + // { + // if (Param == null) + // { + // LSOEngine.LSO.Common.SendToDebug("::PUSH: "); + // } + // else + // { + // //Common.SendToDebug("::PUSH: " + Param.GetType()); + // } + + // LSLStack.Push(Param); + // } + + // public void ADD(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::ADD: " + Param); + // object o2 = LSLStack.Pop(); + // object o1 = LSLStack.Pop(); + // LSOEngine.LSO.Common.SendToDebug("::ADD: Debug: o1: " + o1.GetType() + " (" + o1.ToString() + "), o2: " + o2.GetType() + + // " (" + o2.ToString() + ")"); + // if (o2.GetType() == typeof (string)) + // { + // LSLStack.Push((string) o1 + (string) o2); + // return; + // } + // if (o2.GetType() == typeof (UInt32)) + // { + // LSLStack.Push((UInt32) o1 + (UInt32) o2); + // return; + // } + // } + + // public void SUB(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::SUB: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1 - i2)); + // } + + // public void MUL(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::SUB: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1*i2)); + // } + + // public void DIV(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::DIV: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1/i2)); + // } + + + // public void MOD(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::MOD: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1%i2)); + // } + + // public void EQ(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::EQ: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 == i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void NEQ(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::NEQ: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 != i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void LEQ(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::LEQ: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 <= i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void GEQ(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::GEQ: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 >= i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void LESS(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::LESS: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 < i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void GREATER(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::GREATER: " + Param); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // if (i1 > i2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + + // public void BITAND() + // { + // LSOEngine.LSO.Common.SendToDebug("::BITAND"); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1 & i2)); + // } + + // public void BITOR() + // { + // LSOEngine.LSO.Common.SendToDebug("::BITOR"); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1 | i2)); + // } + + // public void BITXOR() + // { + // LSOEngine.LSO.Common.SendToDebug("::BITXOR"); + // UInt32 i2 = (UInt32) LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1 ^ i2)); + // } + + // public void BOOLAND() + // { + // LSOEngine.LSO.Common.SendToDebug("::BOOLAND"); + // bool b2 = bool.Parse((string) LSLStack.Pop()); + // bool b1 = bool.Parse((string) LSLStack.Pop()); + // if (b1 && b2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void BOOLOR() + // { + // LSOEngine.LSO.Common.SendToDebug("::BOOLOR"); + // bool b2 = bool.Parse((string) LSLStack.Pop()); + // bool b1 = bool.Parse((string) LSLStack.Pop()); + + // if (b1 || b2) + // { + // LSLStack.Push((UInt32) 1); + // } + // else + // { + // LSLStack.Push((UInt32) 0); + // } + // } + + // public void NEG(UInt32 Param) + // { + // LSOEngine.LSO.Common.SendToDebug("::NEG: " + Param); + // //UInt32 i2 = (UInt32)LSLStack.Pop(); + // UInt32 i1 = (UInt32) LSLStack.Pop(); + // LSLStack.Push((UInt32) (i1*-1)); + // } + + // public void BITNOT() + // { + // //Common.SendToDebug("::BITNOT"); + // //UInt32 i2 = (UInt32)LSLStack.Pop(); + // //UInt32 i1 = (UInt32)LSLStack.Pop(); + // //LSLStack.Push((UInt32)(i1 / i2)); + // } + + // public void BOOLNOT() + // { + // //Common.SendToDebug("::BOOLNOT"); + // ////UInt32 i2 = (UInt32)LSLStack.Pop(); + // //UInt32 i1 = (UInt32)LSLStack.Pop(); + // //LSLStack.Push((UInt32)(i1)); + // } + //} +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_CLRInterface.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_CLRInterface.cs new file mode 100644 index 0000000000..8bb7712bf3 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_CLRInterface.cs @@ -0,0 +1,75 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + public class LSL_CLRInterface + { + public interface LSLScript + { + //public virtual void Run(object arg) + //{ + //} + //void Run(object arg); + + //void event_state_entry(object arg); + //void event_state_exit(); + //void event_touch_start(object arg); + //void event_touch(); + //void event_touch_end(); + //void event_collision_start(); + //void event_collision(); + //void event_collision_end(); + //void event_land_collision_start(); + //void event_land_collision(); + //void event_land_collision_end(); + //void event_timer(); + //void event_listen(); + //void event_on_rez(); + //void event_sensor(); + //void event_no_sensor(); + //void event_control(); + //void event_money(); + //void event_email(); + //void event_at_target(); + //void event_not_at_target(); + //void event_at_rot_target(); + //void event_not_at_rot_target(); + //void event_run_time_permissions(); + //void event_changed(); + //void event_attach(); + //void event_dataserver(); + //void event_link_message(); + //void event_moving_start(); + //void event_moving_end(); + //void event_object_rez(); + //void event_remote_data(); + //void event_http_response(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_OPCODE_IL_processor.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_OPCODE_IL_processor.cs new file mode 100644 index 0000000000..30d38905c4 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSL_OPCODE_IL_processor.cs @@ -0,0 +1,435 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Reflection; +using System.Reflection.Emit; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + internal partial class LSO_Parser + { + //internal Stack ILStack = new Stack(); + //LSO_Enums MyLSO_Enums = new LSO_Enums(); + + internal bool LSL_PROCESS_OPCODE(ILGenerator il) + { + byte bp1; + UInt32 u32p1; + float fp1; + UInt16 opcode = br_read(1)[0]; + Common.SendToDebug("OPCODE: " + ((LSO_Enums.Operation_Table) opcode).ToString()); + string idesc = ((LSO_Enums.Operation_Table) opcode).ToString(); + switch ((LSO_Enums.Operation_Table) opcode) + { + /*************** + * IMPLEMENTED * + ***************/ + case LSO_Enums.Operation_Table.NOOP: + break; + case LSO_Enums.Operation_Table.PUSHSP: + // Push Stack Top (Memory Address) to stack + Common.SendToDebug("Instruction " + idesc); + Common.SendToDebug("Instruction " + idesc + + ": Description: Pushing Stack Top (Memory Address from header) to stack"); + IL_Push(il, (UInt32) myHeader.SP); + break; + // BYTE + case LSO_Enums.Operation_Table.PUSHARGB: + Common.SendToDebug("Param1: " + br_read(1)[0]); + break; + // INTEGER + case LSO_Enums.Operation_Table.PUSHARGI: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + u32p1); + IL_Push(il, u32p1); + break; + // FLOAT + case LSO_Enums.Operation_Table.PUSHARGF: + fp1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + fp1); + IL_Push(il, fp1); + break; + // STRING + case LSO_Enums.Operation_Table.PUSHARGS: + string s = Read_String(); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + s); + IL_Debug(il, "OPCODE: " + idesc + ":" + s); + IL_Push(il, s); + break; + // VECTOR z,y,x + case LSO_Enums.Operation_Table.PUSHARGV: + LSO_Enums.Vector v = new LSO_Enums.Vector(); + v.Z = BitConverter.ToUInt32(br_read(4), 0); + v.Y = BitConverter.ToUInt32(br_read(4), 0); + v.X = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1 Z: " + v.Z); + Common.SendToDebug("Param1 Y: " + v.Y); + Common.SendToDebug("Param1 X: " + v.X); + IL_Push(il, v); + break; + // ROTATION s,z,y,x + case LSO_Enums.Operation_Table.PUSHARGQ: + LSO_Enums.Rotation r = new LSO_Enums.Rotation(); + r.S = BitConverter.ToUInt32(br_read(4), 0); + r.Z = BitConverter.ToUInt32(br_read(4), 0); + r.Y = BitConverter.ToUInt32(br_read(4), 0); + r.X = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1 S: " + r.S); + Common.SendToDebug("Param1 Z: " + r.Z); + Common.SendToDebug("Param1 Y: " + r.Y); + Common.SendToDebug("Param1 X: " + r.X); + IL_Push(il, r); + break; + + case LSO_Enums.Operation_Table.PUSHE: + IL_Push(il, (UInt32) 0); + break; + + case LSO_Enums.Operation_Table.PUSHARGE: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1); + //IL_Push(il, new string(" ".ToCharArray()[0], Convert.ToInt32(u32p1))); + IL_Push(il, u32p1); + break; + // BYTE + case LSO_Enums.Operation_Table.ADD: + case LSO_Enums.Operation_Table.SUB: + case LSO_Enums.Operation_Table.MUL: + case LSO_Enums.Operation_Table.DIV: + case LSO_Enums.Operation_Table.EQ: + case LSO_Enums.Operation_Table.NEQ: + case LSO_Enums.Operation_Table.LEQ: + case LSO_Enums.Operation_Table.GEQ: + case LSO_Enums.Operation_Table.LESS: + case LSO_Enums.Operation_Table.GREATER: + case LSO_Enums.Operation_Table.NEG: + case LSO_Enums.Operation_Table.MOD: + bp1 = br_read(1)[0]; + Common.SendToDebug("Param1: " + bp1); + IL_CallBaseFunction(il, idesc, (UInt32) bp1); + break; + + // NO ARGUMENTS + case LSO_Enums.Operation_Table.BITAND: + case LSO_Enums.Operation_Table.BITOR: + case LSO_Enums.Operation_Table.BITXOR: + case LSO_Enums.Operation_Table.BOOLAND: + case LSO_Enums.Operation_Table.BOOLOR: + case LSO_Enums.Operation_Table.BITNOT: + case LSO_Enums.Operation_Table.BOOLNOT: + IL_CallBaseFunction(il, idesc); + break; + // SHORT + case LSO_Enums.Operation_Table.CALLLIB_TWO_BYTE: + // TODO: What is size of short? + UInt16 U16p1 = BitConverter.ToUInt16(br_read(2), 0); + Common.SendToDebug("Instruction " + idesc + ": Builtin Command: " + + ((LSO_Enums.BuiltIn_Functions) U16p1).ToString()); + //Common.SendToDebug("Param1: " + U16p1); + string fname = ((LSO_Enums.BuiltIn_Functions) U16p1).ToString(); + + bool cmdFound = false; + foreach (MethodInfo mi in typeof (LSL_BuiltIn_Commands_Interface).GetMethods()) + { + // Found command + if (mi.Name == fname) + { + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("GetLSL_BuiltIn", new Type[] {})); + // Pop required number of items from my stack to .Net stack + IL_PopToStack(il, mi.GetParameters().Length); + il.Emit(OpCodes.Callvirt, mi); + cmdFound = true; + break; + } + } + if (cmdFound == false) + { + Common.SendToDebug("ERROR: UNABLE TO LOCATE OPCODE " + idesc + " IN BASECLASS"); + } + + break; + + // RETURN + case LSO_Enums.Operation_Table.RETURN: + + Common.SendToDebug("OPCODE: RETURN"); + return true; + + case LSO_Enums.Operation_Table.POP: + case LSO_Enums.Operation_Table.POPS: + case LSO_Enums.Operation_Table.POPL: + case LSO_Enums.Operation_Table.POPV: + case LSO_Enums.Operation_Table.POPQ: + // Pops a specific datatype from the stack + // We just ignore the datatype for now + IL_Pop(il); + break; + + // LONG + case LSO_Enums.Operation_Table.STORE: + case LSO_Enums.Operation_Table.STORES: + case LSO_Enums.Operation_Table.STOREL: + case LSO_Enums.Operation_Table.STOREV: + case LSO_Enums.Operation_Table.STOREQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToLocal", u32p1); + break; + + case LSO_Enums.Operation_Table.STOREG: + case LSO_Enums.Operation_Table.STOREGS: + case LSO_Enums.Operation_Table.STOREGL: + case LSO_Enums.Operation_Table.STOREGV: + case LSO_Enums.Operation_Table.STOREGQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToGlobal", u32p1); + break; + + case LSO_Enums.Operation_Table.LOADP: + case LSO_Enums.Operation_Table.LOADSP: + case LSO_Enums.Operation_Table.LOADLP: + case LSO_Enums.Operation_Table.LOADVP: + case LSO_Enums.Operation_Table.LOADQP: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToLocal", u32p1); + IL_Pop(il); + break; + + case LSO_Enums.Operation_Table.LOADGP: + case LSO_Enums.Operation_Table.LOADGSP: + case LSO_Enums.Operation_Table.LOADGLP: + case LSO_Enums.Operation_Table.LOADGVP: + case LSO_Enums.Operation_Table.LOADGQP: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToStatic", u32p1 - 6 + myHeader.GVR); + IL_Pop(il); + break; + + // PUSH FROM LOCAL FRAME + case LSO_Enums.Operation_Table.PUSH: + case LSO_Enums.Operation_Table.PUSHS: + case LSO_Enums.Operation_Table.PUSHL: + case LSO_Enums.Operation_Table.PUSHV: + case LSO_Enums.Operation_Table.PUSHQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "GetFromLocal", u32p1); + + break; + + // PUSH FROM STATIC FRAME + case LSO_Enums.Operation_Table.PUSHG: + case LSO_Enums.Operation_Table.PUSHGS: + case LSO_Enums.Operation_Table.PUSHGL: + case LSO_Enums.Operation_Table.PUSHGV: + case LSO_Enums.Operation_Table.PUSHGQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "GetFromStatic", u32p1 - 6 + myHeader.GVR); + break; + + + /*********************** + * NOT IMPLEMENTED YET * + ***********************/ + + + case LSO_Enums.Operation_Table.POPIP: + case LSO_Enums.Operation_Table.POPSP: + case LSO_Enums.Operation_Table.POPSLR: + case LSO_Enums.Operation_Table.POPARG: + case LSO_Enums.Operation_Table.POPBP: + //Common.SendToDebug("Instruction " + idesc + ": Ignored"); + Common.SendToDebug("Instruction " + idesc + + ": Description: Drop x bytes from the stack (TODO: Only popping 1)"); + //Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + IL_Pop(il); + break; + + + // None + case LSO_Enums.Operation_Table.PUSHIP: + // PUSH INSTRUCTION POINTER + break; + case LSO_Enums.Operation_Table.PUSHBP: + + case LSO_Enums.Operation_Table.PUSHEV: + break; + case LSO_Enums.Operation_Table.PUSHEQ: + break; + + + // LONG + case LSO_Enums.Operation_Table.JUMP: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // BYTE, LONG + case LSO_Enums.Operation_Table.JUMPIF: + case LSO_Enums.Operation_Table.JUMPNIF: + Common.SendToDebug("Param1: " + br_read(1)[0]); + Common.SendToDebug("Param2: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // LONG + case LSO_Enums.Operation_Table.STATE: + bp1 = br_read(1)[0]; + //il.Emit(OpCodes.Ld); // Load local variable 0 onto stack + //il.Emit(OpCodes.Ldc_I4, 0); // Push index position + //il.Emit(OpCodes.Ldstr, EventList[p1]); // Push value + //il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value + break; + case LSO_Enums.Operation_Table.CALL: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + Common.SendToDebug("ERROR: Function CALL not implemented yet."); + break; + // BYTE + case LSO_Enums.Operation_Table.CAST: + bp1 = br_read(1)[0]; + Common.SendToDebug("Instruction " + idesc + ": Cast to type: " + + ((LSO_Enums.OpCode_Cast_TypeDefs) bp1)); + Common.SendToDebug("Param1: " + bp1); + switch ((LSO_Enums.OpCode_Cast_TypeDefs) bp1) + { + case LSO_Enums.OpCode_Cast_TypeDefs.String: + Common.SendToDebug("Instruction " + idesc + ": il.Emit(OpCodes.Box, ILStack.Pop());"); + break; + default: + Common.SendToDebug("Instruction " + idesc + ": Unknown cast type!"); + break; + } + break; + // LONG + case LSO_Enums.Operation_Table.STACKTOS: + case LSO_Enums.Operation_Table.STACKTOL: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // BYTE + case LSO_Enums.Operation_Table.PRINT: + case LSO_Enums.Operation_Table.CALLLIB: + Common.SendToDebug("Param1: " + br_read(1)[0]); + break; + } + return false; + } + + private void IL_PopToStack(ILGenerator il) + { + IL_PopToStack(il, 1); + } + + private void IL_PopToStack(ILGenerator il, int count) + { + Common.SendToDebug("IL_PopToStack();"); + for (int i = 0; i < count; i++) + { + IL_CallBaseFunction(il, "POPToStack"); + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Call, + // typeof(LSL_BaseClass).GetMethod("POPToStack", + // new Type[] { })); + } + } + + private void IL_Pop(ILGenerator il) + { + Common.SendToDebug("IL_Pop();"); + IL_CallBaseFunction(il, "POP"); + } + + private void IL_Debug(ILGenerator il, string text) + { + il.Emit(OpCodes.Ldstr, text); + il.Emit(OpCodes.Call, typeof (Common).GetMethod("SendToDebug", + new Type[] {typeof (string)} + )); + } + + private void IL_CallBaseFunction(ILGenerator il, string methodname) + { + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {})); + } + + private void IL_CallBaseFunction(ILGenerator il, string methodname, object data) + { + il.Emit(OpCodes.Ldarg_0); + if (data.GetType() == typeof (string)) + il.Emit(OpCodes.Ldstr, (string) data); + if (data.GetType() == typeof (UInt32)) + il.Emit(OpCodes.Ldc_I4, (UInt32) data); + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod(methodname, new Type[] {data.GetType()})); + } + + private void IL_Push(ILGenerator il, object data) + { + il.Emit(OpCodes.Ldarg_0); + Common.SendToDebug("PUSH datatype: " + data.GetType()); + + IL_PushDataTypeToILStack(il, data); + + il.Emit(OpCodes.Call, typeof (LSL_BaseClass).GetMethod("PUSH", new Type[] {data.GetType()})); + } + + private void IL_PushDataTypeToILStack(ILGenerator il, object data) + { + if (data.GetType() == typeof (UInt16)) + { + il.Emit(OpCodes.Ldc_I4, (UInt16) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (UInt32)) + { + il.Emit(OpCodes.Ldc_I4, (UInt32) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (Int32)) + { + il.Emit(OpCodes.Ldc_I4, (Int32) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (float)) + { + il.Emit(OpCodes.Ldc_I4, (float) data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof (string)) + il.Emit(OpCodes.Ldstr, (string) data); + //if (data.GetType() == typeof(LSO_Enums.Rotation)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Rotation)data); + //if (data.GetType() == typeof(LSO_Enums.Vector)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Vector)data); + //if (data.GetType() == typeof(LSO_Enums.Key)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Key)data); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Enums.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Enums.cs new file mode 100644 index 0000000000..ea84efd850 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Enums.cs @@ -0,0 +1,560 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + public static class LSO_Enums + { + //public System.Collections.Generic.Dictionary OpCode_Add_Types; + + //LSO_Enums() { + // OpCode_Add_Types.Add(51, typeof(String)); + // OpCode_Add_Types.Add(17, typeof(UInt32)); + //} + + [Serializable] + public enum OpCode_Add_TypeDefs + { + String = 51, + UInt32 = 17 + } + + [Serializable] + public enum OpCode_Cast_TypeDefs + { + String = 19 + } + + [Serializable] + public struct Key + { + public string KeyString; + } + + [Serializable] + public struct Vector + { + public UInt32 Z; + public UInt32 Y; + public UInt32 X; + } + + [Serializable] + public struct Rotation + { + public UInt32 S; + public UInt32 Z; + public UInt32 Y; + public UInt32 X; + } + + [Serializable] + public enum Variable_Type_Codes + { + Void = 0, + Integer = 1, + Float = 2, + String = 3, + Key = 4, + Vector = 5, + Rotation = 6, + List = 7, + Null = 8 + } + + [Serializable] + public enum Event_Mask_Values + { + state_entry = 0, + state_exit = 1, + touch_start = 2, + touch = 3, + touch_end = 4, + collision_start = 5, + collision = 6, + collision_end = 7, + land_collision_start = 8, + land_collision = 9, + land_collision_end = 10, + timer = 11, + listen = 12, + on_rez = 13, + sensor = 14, + no_sensor = 15, + control = 16, + money = 17, + email = 18, + at_target = 19, + not_at_target = 20, + at_rot_target = 21, + not_at_rot_target = 22, + run_time_permissions = 23, + changed = 24, + attach = 25, + dataserver = 26, + link_message = 27, + moving_start = 28, + moving_end = 29, + object_rez = 30, + remote_data = 31, + http_response = 32 + } + + [Serializable] + public enum Operation_Table + { + NOOP = 0x0, + POP = 0x1, + POPS = 0x2, + POPL = 0x3, + POPV = 0x4, + POPQ = 0x5, + POPARG = 0x6, + POPIP = 0x7, + POPBP = 0x8, + POPSP = 0x9, + POPSLR = 0xa, + DUP = 0x20, + DUPS = 0x21, + DUPL = 0x22, + DUPV = 0x23, + DUPQ = 0x24, + STORE = 0x30, + STORES = 0x31, + STOREL = 0x32, + STOREV = 0x33, + STOREQ = 0x34, + STOREG = 0x35, + STOREGS = 0x36, + STOREGL = 0x37, + STOREGV = 0x38, + STOREGQ = 0x39, + LOADP = 0x3a, + LOADSP = 0x3b, + LOADLP = 0x3c, + LOADVP = 0x3d, + LOADQP = 0x3e, + LOADGP = 0x3f, + LOADGSP = 0x40, + LOADGLP = 0x41, + LOADGVP = 0x42, + LOADGQP = 0x43, + PUSH = 0x50, + PUSHS = 0x51, + PUSHL = 0x52, + PUSHV = 0x53, + PUSHQ = 0x54, + PUSHG = 0x55, + PUSHGS = 0x56, + PUSHGL = 0x57, + PUSHGV = 0x58, + PUSHGQ = 0x59, + PUSHIP = 0x5a, + PUSHBP = 0x5b, + PUSHSP = 0x5c, + PUSHARGB = 0x5d, + PUSHARGI = 0x5e, + PUSHARGF = 0x5f, + PUSHARGS = 0x60, + PUSHARGV = 0x61, + PUSHARGQ = 0x62, + PUSHE = 0x63, + PUSHEV = 0x64, + PUSHEQ = 0x65, + PUSHARGE = 0x66, + ADD = 0x70, + SUB = 0x71, + MUL = 0x72, + DIV = 0x73, + MOD = 0x74, + EQ = 0x75, + NEQ = 0x76, + LEQ = 0x77, + GEQ = 0x78, + LESS = 0x79, + GREATER = 0x7a, + BITAND = 0x7b, + BITOR = 0x7c, + BITXOR = 0x7d, + BOOLAND = 0x7e, + BOOLOR = 0x7f, + NEG = 0x80, + BITNOT = 0x81, + BOOLNOT = 0x82, + JUMP = 0x90, + JUMPIF = 0x91, + JUMPNIF = 0x92, + STATE = 0x93, + CALL = 0x94, + RETURN = 0x95, + CAST = 0xa0, + STACKTOS = 0xb0, + STACKTOL = 0xb1, + PRINT = 0xc0, + CALLLIB = 0xd0, + CALLLIB_TWO_BYTE = 0xd1, + SHL = 0xe0, + SHR = 0xe1 + } + + [Serializable] + public enum BuiltIn_Functions + { + llSin = 0, + llCos = 1, + llTan = 2, + llAtan2 = 3, + llSqrt = 4, + llPow = 5, + llAbs = 6, + llFabs = 7, + llFrand = 8, + llFloor = 9, + llCeil = 10, + llRound = 11, + llVecMag = 12, + llVecNorm = 13, + llVecDist = 14, + llRot2Euler = 15, + llEuler2Rot = 16, + llAxes2Rot = 17, + llRot2Fwd = 18, + llRot2Left = 19, + llRot2Up = 20, + llRotBetween = 21, + llWhisper = 22, + llSay = 23, + llShout = 24, + llListen = 25, + llListenControl = 26, + llListenRemove = 27, + llSensor = 28, + llSensorRepeat = 29, + llSensorRemove = 30, + llDetectedName = 31, + llDetectedKey = 32, + llDetectedOwner = 33, + llDetectedType = 34, + llDetectedPos = 35, + llDetectedVel = 36, + llDetectedGrab = 37, + llDetectedRot = 38, + llDetectedGroup = 39, + llDetectedLinkNumber = 40, + llDie = 41, + llGround = 42, + llCloud = 43, + llWind = 44, + llSetStatus = 45, + llGetStatus = 46, + llSetScale = 47, + llGetScale = 48, + llSetColor = 49, + llGetAlpha = 50, + llSetAlpha = 51, + llGetColor = 52, + llSetTexture = 53, + llScaleTexture = 54, + llOffsetTexture = 55, + llRotateTexture = 56, + llGetTexture = 57, + llSetPos = 58, + llGetPos = 59, + llGetLocalPos = 60, + llSetRot = 61, + llGetRot = 62, + llGetLocalRot = 63, + llSetForce = 64, + llGetForce = 65, + llTarget = 66, + llTargetRemove = 67, + llRotTarget = 68, + llRotTargetRemove = 69, + llMoveToTarget = 70, + llStopMoveToTarget = 71, + llApplyImpulse = 72, + llApplyRotationalImpulse = 73, + llSetTorque = 74, + llGetTorque = 75, + llSetForceAndTorque = 76, + llGetVel = 77, + llGetAccel = 78, + llGetOmega = 79, + llGetTimeOfDay = 80, + llGetWallclock = 81, + llGetTime = 82, + llResetTime = 83, + llGetAndResetTime = 84, + llSound = 85, + llPlaySound = 86, + llLoopSound = 87, + llLoopSoundMaster = 88, + llLoopSoundSlave = 89, + llPlaySoundSlave = 90, + llTriggerSound = 91, + llStopSound = 92, + llPreloadSound = 93, + llGetSubString = 94, + llDeleteSubString = 95, + llInsertString = 96, + llToUpper = 97, + llToLower = 98, + llGiveMoney = 99, + llMakeExplosion = 100, + llMakeFountain = 101, + llMakeSmoke = 102, + llMakeFire = 103, + llRezObject = 104, + llLookAt = 105, + llStopLookAt = 106, + llSetTimerEvent = 107, + llSleep = 108, + llGetMass = 109, + llCollisionFilter = 110, + llTakeControls = 111, + llReleaseControls = 112, + llAttachToAvatar = 113, + llDetachFromAvatar = 114, + llTakeCamera = 115, + llReleaseCamera = 116, + llGetOwner = 117, + llInstantMessage = 118, + llEmail = 119, + llGetNextEmail = 120, + llGetKey = 121, + llSetBuoyancy = 122, + llSetHoverHeight = 123, + llStopHover = 124, + llMinEventDelay = 125, + llSoundPreload = 126, + llRotLookAt = 127, + llStringLength = 128, + llStartAnimation = 129, + llStopAnimation = 130, + llPointAt = 131, + llStopPointAt = 132, + llTargetOmega = 133, + llGetStartParameter = 134, + llGodLikeRezObject = 135, + llRequestPermissions = 136, + llGetPermissionsKey = 137, + llGetPermissions = 138, + llGetLinkNumber = 139, + llSetLinkColor = 140, + llCreateLink = 141, + llBreakLink = 142, + llBreakAllLinks = 143, + llGetLinkKey = 144, + llGetLinkName = 145, + llGetInventoryNumber = 146, + llGetInventoryName = 147, + llSetScriptState = 148, + llGetEnergy = 149, + llGiveInventory = 150, + llRemoveInventory = 151, + llSetText = 152, + llWater = 153, + llPassTouches = 154, + llRequestAgentData = 155, + llRequestInventoryData = 156, + llSetDamage = 157, + llTeleportAgentHome = 158, + llModifyLand = 159, + llCollisionSound = 160, + llCollisionSprite = 161, + llGetAnimation = 162, + llResetScript = 163, + llMessageLinked = 164, + llPushObject = 165, + llPassCollisions = 166, + llGetScriptName = 167, + llGetNumberOfSides = 168, + llAxisAngle2Rot = 169, + llRot2Axis = 170, + llRot2Angle = 171, + llAcos = 172, + llAsin = 173, + llAngleBetween = 174, + llGetInventoryKey = 175, + llAllowInventoryDrop = 176, + llGetSunDirection = 177, + llGetTextureOffset = 178, + llGetTextureScale = 179, + llGetTextureRot = 180, + llSubStringIndex = 181, + llGetOwnerKey = 182, + llGetCenterOfMass = 183, + llListSort = 184, + llGetListLength = 185, + llList2Integer = 186, + llList2Float = 187, + llList2String = 188, + llList2Key = 189, + llList2Vector = 190, + llList2Rot = 191, + llList2List = 192, + llDeleteSubList = 193, + llGetListEntryType = 194, + llList2CSV = 195, + llCSV2List = 196, + llListRandomize = 197, + llList2ListStrided = 198, + llGetRegionCorner = 199, + llListInsertList = 200, + llListFindList = 201, + llGetObjectName = 202, + llSetObjectName = 203, + llGetDate = 204, + llEdgeOfWorld = 205, + llGetAgentInfo = 206, + llAdjustSoundVolume = 207, + llSetSoundQueueing = 208, + llSetSoundRadius = 209, + llKey2Name = 210, + llSetTextureAnim = 211, + llTriggerSoundLimited = 212, + llEjectFromLand = 213, + llParseString2List = 214, + llOverMyLand = 215, + llGetLandOwnerAt = 216, + llGetNotecardLine = 217, + llGetAgentSize = 218, + llSameGroup = 219, + llUnSit = 220, + llGroundSlope = 221, + llGroundNormal = 222, + llGroundContour = 223, + llGetAttached = 224, + llGetFreeMemory = 225, + llGetRegionName = 226, + llGetRegionTimeDilation = 227, + llGetRegionFPS = 228, + llParticleSystem = 229, + llGroundRepel = 230, + llGiveInventoryList = 231, + llSetVehicleType = 232, + llSetVehicleFloatParam = 233, + llSetVehicleVectorParam = 234, + llSetVehicleRotationParam = 235, + llSetVehicleFlags = 236, + llRemoveVehicleFlags = 237, + llSitTarget = 238, + llAvatarOnSitTarget = 239, + llAddToLandPassList = 240, + llSetTouchText = 241, + llSetSitText = 242, + llSetCameraEyeOffset = 243, + llSetCameraAtOffset = 244, + llDumpList2String = 245, + llScriptDanger = 246, + llDialog = 247, + llVolumeDetect = 248, + llResetOtherScript = 249, + llGetScriptState = 250, + llRemoteLoadScript = 251, + llSetRemoteScriptAccessPin = 252, + llRemoteLoadScriptPin = 253, + llOpenRemoteDataChannel = 254, + llSendRemoteData = 255, + llRemoteDataReply = 256, + llCloseRemoteDataChannel = 257, + llMD5String = 258, + llSetPrimitiveParams = 259, + llStringToBase64 = 260, + llBase64ToString = 261, + llXorBase64Strings = 262, + llRemoteDataSetRegion = 263, + llLog10 = 264, + llLog = 265, + llGetAnimationList = 266, + llSetParcelMusicURL = 267, + llGetRootPosition = 268, + llGetRootRotation = 269, + llGetObjectDesc = 270, + llSetObjectDesc = 271, + llGetCreator = 272, + llGetTimestamp = 273, + llSetLinkAlpha = 274, + llGetNumberOfPrims = 275, + llGetNumberOfNotecardLines = 276, + llGetBoundingBox = 277, + llGetGeometricCenter = 278, + llGetPrimitiveParams = 279, + llIntegerToBase64 = 280, + llBase64ToInteger = 281, + llGetGMTclock = 282, + llGetSimulatorHostname = 283, + llSetLocalRot = 284, + llParseStringKeepNulls = 285, + llRezAtRoot = 286, + llGetObjectPermMask = 287, + llSetObjectPermMask = 288, + llGetInventoryPermMask = 289, + llSetInventoryPermMask = 290, + llGetInventoryCreator = 291, + llOwnerSay = 292, + llRequestSimulatorData = 293, + llForceMouselook = 294, + llGetObjectMass = 295, + llListReplaceList = 296, + llLoadURL = 297, + llParcelMediaCommandList = 298, + llParcelMediaQuery = 299, + llModPow = 300, + llGetInventoryType = 301, + llSetPayPrice = 302, + llGetCameraPos = 303, + llGetCameraRot = 304, + llSetPrimURL = 305, + llRefreshPrimURL = 306, + llEscapeURL = 307, + llUnescapeURL = 308, + llMapDestination = 309, + llAddToLandBanList = 310, + llRemoveFromLandPassList = 311, + llRemoveFromLandBanList = 312, + llSetCameraParams = 313, + llClearCameraParams = 314, + llListStatistics = 315, + llGetUnixTime = 316, + llGetParcelFlags = 317, + llGetRegionFlags = 318, + llXorBase64StringsCorrect = 319, + llHTTPRequest = 320, + llResetLandBanList = 321, + llResetLandPassList = 322, + llGetParcelPrimCount = 323, + llGetParcelPrimOwners = 324, + llGetObjectPrimCount = 325, + llGetParcelMaxPrims = 326, + llGetParcelDetails = 327 + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Parser.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Parser.cs new file mode 100644 index 0000000000..e1fff5c726 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Parser.cs @@ -0,0 +1,729 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using OpenSim.Region.ScriptEngine.LSOEngine.LSO; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + internal partial class LSO_Parser + { + private string FileName; + private FileStream fs; + private BinaryReader br; + internal LSO_Struct.Header myHeader; + internal Dictionary StaticBlocks = new Dictionary(); + //private System.Collections.Hashtable StaticBlocks = new System.Collections.Hashtable(); + + private TypeBuilder typeBuilder; + private List EventList = new List(); + + public LSO_Parser(string _FileName, TypeBuilder _typeBuilder) + { + FileName = _FileName; + typeBuilder = _typeBuilder; + } + + internal void OpenFile() + { + // Open + Common.SendToDebug("Opening filename: " + FileName); + fs = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.Read); + br = new BinaryReader(fs, Encoding.BigEndianUnicode); + } + + internal void CloseFile() + { + // Close + br.Close(); + fs.Close(); + } + + + /// + /// Parse LSO file. + /// + public void Parse() + { + // The LSO Format consist of 6 major blocks: header, statics, functions, states, heap, and stack. + + + // HEADER BLOCK + Common.SendToDebug("Reading HEADER BLOCK at: 0"); + fs.Seek(0, SeekOrigin.Begin); + myHeader = new LSO_Struct.Header(); + myHeader.TM = BitConverter.ToUInt32(br_read(4), 0); + myHeader.IP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.VN = BitConverter.ToUInt32(br_read(4), 0); + myHeader.BP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.HR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.HP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.CS = BitConverter.ToUInt32(br_read(4), 0); + myHeader.NS = BitConverter.ToUInt32(br_read(4), 0); + myHeader.CE = BitConverter.ToUInt32(br_read(4), 0); + myHeader.IE = BitConverter.ToUInt32(br_read(4), 0); + myHeader.ER = BitConverter.ToUInt32(br_read(4), 0); + myHeader.FR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SLR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.GVR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.GFR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.PR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.ESR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.NCE = BitConverter.ToUInt64(br_read(8), 0); + myHeader.NIE = BitConverter.ToUInt64(br_read(8), 0); + myHeader.NER = BitConverter.ToUInt64(br_read(8), 0); + + // Print Header Block to debug + Common.SendToDebug("TM - Top of memory (size): " + myHeader.TM); + Common.SendToDebug("IP - Instruction Pointer (0=not running): " + myHeader.IP); + Common.SendToDebug("VN - Version number: " + myHeader.VN); + Common.SendToDebug("BP - Local Frame Pointer: " + myHeader.BP); + Common.SendToDebug("SP - Stack Pointer: " + myHeader.SP); + Common.SendToDebug("HR - Heap Register: " + myHeader.HR); + Common.SendToDebug("HP - Heap Pointer: " + myHeader.HP); + Common.SendToDebug("CS - Current State: " + myHeader.CS); + Common.SendToDebug("NS - Next State: " + myHeader.NS); + Common.SendToDebug("CE - Current Events: " + myHeader.CE); + Common.SendToDebug("IE - In Event: " + myHeader.IE); + Common.SendToDebug("ER - Event Register: " + myHeader.ER); + Common.SendToDebug("FR - Fault Register: " + myHeader.FR); + Common.SendToDebug("SLR - Sleep Register: " + myHeader.SLR); + Common.SendToDebug("GVR - Global Variable Register: " + myHeader.GVR); + Common.SendToDebug("GFR - Global Function Register: " + myHeader.GFR); + Common.SendToDebug("PR - Parameter Register: " + myHeader.PR); + Common.SendToDebug("ESR - Energy Supply Register: " + myHeader.ESR); + Common.SendToDebug("SR - State Register: " + myHeader.SR); + Common.SendToDebug("NCE - 64-bit Current Events: " + myHeader.NCE); + Common.SendToDebug("NIE - 64-bit In Events: " + myHeader.NIE); + Common.SendToDebug("NER - 64-bit Event Register: " + myHeader.NER); + Common.SendToDebug("Read position when exiting HEADER BLOCK: " + fs.Position); + + // STATIC BLOCK + Common.SendToDebug("Reading STATIC BLOCK at: " + myHeader.GVR); + fs.Seek(myHeader.GVR, SeekOrigin.Begin); + int StaticBlockCount = 0; + // Read function blocks until we hit GFR + while (fs.Position < myHeader.GFR) + { + StaticBlockCount++; + long startReadPos = fs.Position; + Common.SendToDebug("Reading Static Block " + StaticBlockCount + " at: " + startReadPos); + + //fs.Seek(myHeader.GVR, SeekOrigin.Begin); + LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); + myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); + myStaticBlock.ObjectType = br_read(1)[0]; + Common.SendToDebug("Static Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myStaticBlock.ObjectType).ToString()); + myStaticBlock.Unknown = br_read(1)[0]; + // Size of datatype varies -- what about strings? + if (myStaticBlock.ObjectType != 0) + myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); + + StaticBlocks.Add((UInt32) startReadPos, myStaticBlock); + } + Common.SendToDebug("Number of Static Blocks read: " + StaticBlockCount); + + + // FUNCTION BLOCK + // Always right after STATIC BLOCK + LSO_Struct.FunctionBlock myFunctionBlock = new LSO_Struct.FunctionBlock(); + if (myHeader.GFR == myHeader.SR) + { + // If GFR and SR are at same position then there is no fuction block + Common.SendToDebug("No FUNCTION BLOCK found"); + } + else + { + Common.SendToDebug("Reading FUNCTION BLOCK at: " + myHeader.GFR); + fs.Seek(myHeader.GFR, SeekOrigin.Begin); + myFunctionBlock.FunctionCount = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Number of functions in Fuction Block: " + myFunctionBlock.FunctionCount); + if (myFunctionBlock.FunctionCount > 0) + { + myFunctionBlock.CodeChunkPointer = new UInt32[myFunctionBlock.FunctionCount]; + for (int i = 0; i < myFunctionBlock.FunctionCount; i++) + { + Common.SendToDebug("Reading function " + i + " at: " + fs.Position); + // TODO: ADD TO FUNCTION LIST (How do we identify it later?) + // Note! Absolute position + myFunctionBlock.CodeChunkPointer[i] = BitConverter.ToUInt32(br_read(4), 0) + myHeader.GFR; + Common.SendToDebug("Fuction " + i + " code chunk position: " + + myFunctionBlock.CodeChunkPointer[i]); + } + } + } + + + // STATE FRAME BLOCK + // Always right after FUNCTION BLOCK + Common.SendToDebug("Reading STATE BLOCK at: " + myHeader.SR); + fs.Seek(myHeader.SR, SeekOrigin.Begin); + LSO_Struct.StateFrameBlock myStateFrameBlock = new LSO_Struct.StateFrameBlock(); + myStateFrameBlock.StateCount = BitConverter.ToUInt32(br_read(4), 0); + if (myStateFrameBlock.StateCount > 0) + { + // Initialize array + myStateFrameBlock.StatePointer = new LSO_Struct.StatePointerBlock[myStateFrameBlock.StateCount]; + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + Common.SendToDebug("Reading STATE POINTER BLOCK " + (i + 1) + " at: " + fs.Position); + // Position is relative to state frame + myStateFrameBlock.StatePointer[i].Location = myHeader.SR + BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].EventMask = new BitArray(br_read(8)); + Common.SendToDebug("Pointer: " + myStateFrameBlock.StatePointer[i].Location); + Common.SendToDebug("Total potential EventMask bits: " + + myStateFrameBlock.StatePointer[i].EventMask.Count); + + //// Read STATE BLOCK + //long CurPos = fs.Position; + //fs.Seek(CurPos, SeekOrigin.Begin); + } + } + + + // STATE BLOCK + // For each StateFrameBlock there is one StateBlock with multiple event handlers + + if (myStateFrameBlock.StateCount > 0) + { + // Go through all State Frame Pointers found + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + fs.Seek(myStateFrameBlock.StatePointer[i].Location, SeekOrigin.Begin); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " at: " + fs.Position); + + // READ: STATE BLOCK HEADER + myStateFrameBlock.StatePointer[i].StateBlock = new LSO_Struct.StateBlock(); + myStateFrameBlock.StatePointer[i].StateBlock.StartPos = (UInt32) fs.Position; // Note + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize = BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].StateBlock.Unknown = br_read(1)[0]; + myStateFrameBlock.StatePointer[i].StateBlock.EndPos = (UInt32) fs.Position; // Note + Common.SendToDebug("State block Start Pos: " + myStateFrameBlock.StatePointer[i].StateBlock.StartPos); + Common.SendToDebug("State block Header Size: " + + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize); + Common.SendToDebug("State block Header End Pos: " + + myStateFrameBlock.StatePointer[i].StateBlock.EndPos); + + // We need to count number of bits flagged in EventMask? + + + // for each bit in myStateFrameBlock.StatePointer[i].EventMask + + // ADDING TO ALL RIGHT NOW, SHOULD LIMIT TO ONLY THE ONES IN USE + //TODO: Create event hooks + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers = + new LSO_Struct.StateBlockHandler[myStateFrameBlock.StatePointer[i].EventMask.Count - 1]; + for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) + { + if (myStateFrameBlock.StatePointer[i].EventMask.Get(ii) == true) + { + // We got an event + // READ: STATE BLOCK HANDLER + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER matching EVENT MASK " + ii + + " (" + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") at: " + + fs.Position); + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer = + myStateFrameBlock.StatePointer[i].StateBlock.EndPos + + BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CallFrameSize = + BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") Code Chunk Pointer: " + + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii]. + CodeChunkPointer); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + + ((LSO_Enums.Event_Mask_Values) ii).ToString() + ") Call Frame Size: " + + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii]. + CallFrameSize); + } + } + } + } + + + //// READ FUNCTION CODE CHUNKS + //// Functions + Function start pos (GFR) + //// TODO: Somehow be able to identify and reference this + //LSO_Struct.CodeChunk[] myFunctionCodeChunk; + //if (myFunctionBlock.FunctionCount > 0) + //{ + // myFunctionCodeChunk = new LSO_Struct.CodeChunk[myFunctionBlock.FunctionCount]; + // for (int i = 0; i < myFunctionBlock.FunctionCount; i++) + // { + // Common.SendToDebug("Reading Function Code Chunk " + i); + // myFunctionCodeChunk[i] = GetCodeChunk((UInt32)myFunctionBlock.CodeChunkPointer[i]); + // } + + //} + // READ EVENT CODE CHUNKS + LSO_Struct.CodeChunk[] myEventCodeChunk; + if (myStateFrameBlock.StateCount > 0) + { + myEventCodeChunk = new LSO_Struct.CodeChunk[myStateFrameBlock.StateCount]; + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + // TODO: Somehow organize events and functions so they can be found again, + // two level search ain't no good + for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) + { + if (myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer > 0) + { + Common.SendToDebug("Reading Event Code Chunk state " + i + ", event " + + (LSO_Enums.Event_Mask_Values) ii); + + + // Override a Method / Function + string eventname = i + "_event_" + (LSO_Enums.Event_Mask_Values) ii; + Common.SendToDebug("Event Name: " + eventname); + if (Common.IL_ProcessCodeChunks) + { + EventList.Add(eventname); + + // JUMP TO CODE PROCESSOR + ProcessCodeChunk( + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer, + typeBuilder, eventname); + } + } + } + } + } + + + if (Common.IL_CreateFunctionList) + IL_INSERT_FUNCTIONLIST(); + } + + internal LSO_Struct.HeapBlock GetHeap(UInt32 pos) + { + // HEAP BLOCK + // TODO:? Special read for strings/keys (null terminated) and lists (pointers to other HEAP entries) + Common.SendToDebug("Reading HEAP BLOCK at: " + pos); + fs.Seek(pos, SeekOrigin.Begin); + + LSO_Struct.HeapBlock myHeapBlock = new LSO_Struct.HeapBlock(); + myHeapBlock.DataBlockSize = BitConverter.ToInt32(br_read(4), 0); + myHeapBlock.ObjectType = br_read(1)[0]; + myHeapBlock.ReferenceCount = BitConverter.ToUInt16(br_read(2), 0); + //myHeapBlock.Data = br_read(getObjectSize(myHeapBlock.ObjectType)); + // Don't read it reversed + myHeapBlock.Data = new byte[myHeapBlock.DataBlockSize - 1]; + br.Read(myHeapBlock.Data, 0, myHeapBlock.DataBlockSize - 1); + + + Common.SendToDebug("Heap Block Data Block Size: " + myHeapBlock.DataBlockSize); + Common.SendToDebug("Heap Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myHeapBlock.ObjectType).ToString()); + Common.SendToDebug("Heap Block Reference Count: " + myHeapBlock.ReferenceCount); + + return myHeapBlock; + } + + private byte[] br_read(int len) + { + if (len <= 0) + return null; + + try + { + byte[] bytes = new byte[len]; + for (int i = len - 1; i > -1; i--) + bytes[i] = br.ReadByte(); + return bytes; + } + catch (Exception e) // NOTLEGIT: No user related exceptions throwable here? + { + Common.SendToDebug("Exception: " + e.ToString()); + throw (e); + } + } + + //private byte[] br_read_smallendian(int len) + //{ + // byte[] bytes = new byte[len]; + // br.Read(bytes,0, len); + // return bytes; + //} + private Type getLLObjectType(byte objectCode) + { + switch ((LSO_Enums.Variable_Type_Codes) objectCode) + { + case LSO_Enums.Variable_Type_Codes.Void: + return typeof (void); + case LSO_Enums.Variable_Type_Codes.Integer: + return typeof (UInt32); + case LSO_Enums.Variable_Type_Codes.Float: + return typeof (float); + case LSO_Enums.Variable_Type_Codes.String: + return typeof (string); + case LSO_Enums.Variable_Type_Codes.Key: + return typeof (string); + case LSO_Enums.Variable_Type_Codes.Vector: + return typeof (LSO_Enums.Vector); + case LSO_Enums.Variable_Type_Codes.Rotation: + return typeof (LSO_Enums.Rotation); + case LSO_Enums.Variable_Type_Codes.List: + Common.SendToDebug("TODO: List datatype not implemented yet!"); + return typeof (ArrayList); + case LSO_Enums.Variable_Type_Codes.Null: + Common.SendToDebug("TODO: Datatype null is not implemented, using string instead.!"); + return typeof (string); + default: + Common.SendToDebug("Lookup of LSL datatype " + objectCode + + " to .Net datatype failed: Unknown LSL datatype. Defaulting to object."); + return typeof (object); + } + } + + private int getObjectSize(byte ObjectType) + { + switch ((LSO_Enums.Variable_Type_Codes) ObjectType) + { + case LSO_Enums.Variable_Type_Codes.Integer: + case LSO_Enums.Variable_Type_Codes.Float: + case LSO_Enums.Variable_Type_Codes.String: + case LSO_Enums.Variable_Type_Codes.Key: + case LSO_Enums.Variable_Type_Codes.List: + return 4; + case LSO_Enums.Variable_Type_Codes.Vector: + return 12; + case LSO_Enums.Variable_Type_Codes.Rotation: + return 16; + default: + return 0; + } + } + + private string Read_String() + { + string ret = String.Empty; + byte reader = br_read(1)[0]; + while (reader != 0x000) + { + ret += (char) reader; + reader = br_read(1)[0]; + } + return ret; + } + + /// + /// Reads a code chunk and creates IL + /// + /// Absolute position in file. REMEMBER TO ADD myHeader.GFR! + /// TypeBuilder for assembly + /// Name of event (function) to generate + private void ProcessCodeChunk(UInt32 pos, TypeBuilder typeBuilder, string eventname) + { + LSO_Struct.CodeChunk myCodeChunk = new LSO_Struct.CodeChunk(); + + Common.SendToDebug("Reading Function Code Chunk at: " + pos); + fs.Seek(pos, SeekOrigin.Begin); + myCodeChunk.CodeChunkHeaderSize = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("CodeChunk Header Size: " + myCodeChunk.CodeChunkHeaderSize); + // Read until null + myCodeChunk.Comment = Read_String(); + Common.SendToDebug("Function comment: " + myCodeChunk.Comment); + myCodeChunk.ReturnTypePos = br_read(1)[0]; + myCodeChunk.ReturnType = GetStaticBlock((long) myCodeChunk.ReturnTypePos + (long) myHeader.GVR); + Common.SendToDebug("Return type #" + myCodeChunk.ReturnType.ObjectType + ": " + + ((LSO_Enums.Variable_Type_Codes) myCodeChunk.ReturnType.ObjectType).ToString()); + + + // TODO: How to determine number of codechunks -- does this method work? + myCodeChunk.CodeChunkArguments = new List(); + byte reader = br_read(1)[0]; + reader = br_read(1)[0]; + + // NOTE ON CODE CHUNK ARGUMENTS + // This determins type definition + int ccount = 0; + while (reader != 0x000) + { + ccount++; + Common.SendToDebug("Reading Code Chunk Argument " + ccount); + LSO_Struct.CodeChunkArgument CCA = new LSO_Struct.CodeChunkArgument(); + CCA.FunctionReturnTypePos = reader; + reader = br_read(1)[0]; + CCA.NullString = reader; + CCA.FunctionReturnType = GetStaticBlock(CCA.FunctionReturnTypePos + myHeader.GVR); + myCodeChunk.CodeChunkArguments.Add(CCA); + Common.SendToDebug("Code Chunk Argument " + ccount + " type #" + CCA.FunctionReturnType.ObjectType + + ": " + (LSO_Enums.Variable_Type_Codes) CCA.FunctionReturnType.ObjectType); + } + // Create string array + Type[] MethodArgs = new Type[myCodeChunk.CodeChunkArguments.Count]; + for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++) + { + MethodArgs[_ic] = getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType); + Common.SendToDebug("Method argument " + _ic + ": " + + getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType). + ToString()); + } + // End marker is 0x000 + myCodeChunk.EndMarker = reader; + + + // + // Emit: START OF METHOD (FUNCTION) + // + + Common.SendToDebug("CLR:" + eventname + ":MethodBuilder methodBuilder = typeBuilder.DefineMethod..."); + MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, + MethodAttributes.Public, + typeof (void), + new Type[] {typeof (object)}); + //MethodArgs); + //typeof(void), //getLLObjectType(myCodeChunk.ReturnType), + // new Type[] { typeof(object) }, //); + + //Common.SendToDebug("CLR:" + eventname + ":typeBuilder.DefineMethodOverride(methodBuilder..."); + //typeBuilder.DefineMethodOverride(methodBuilder, + // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); + + // Create the IL generator + + Common.SendToDebug("CLR:" + eventname + ":ILGenerator il = methodBuilder.GetILGenerator();"); + ILGenerator il = methodBuilder.GetILGenerator(); + + + if (Common.IL_UseTryCatch) + IL_INSERT_TRY(il, eventname); + + + // Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); + //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + //il.Emit(OpCodes.Call, typeof(Console).GetMethod + // ("WriteLine", new Type[] { typeof(string) })); + + //Common.SendToDebug("STARTUP: il.Emit(OpCodes.Ldc_I4_S, 0);"); + + //il.Emit(OpCodes.Ldc_I4_S, 0); + for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++) + { + Common.SendToDebug("PARAMS: il.Emit(OpCodes.Ldarg, " + _ic + ");"); + il.Emit(OpCodes.Ldarg, _ic); + } + + + // + // CALLING OPCODE PROCESSOR, one command at the time TO GENERATE IL + // + bool FoundRet = false; + while (FoundRet == false) + { + FoundRet = LSL_PROCESS_OPCODE(il); + } + + + if (Common.IL_UseTryCatch) + IL_INSERT_END_TRY(il, eventname); + + // Emit: RETURN FROM METHOD + il.Emit(OpCodes.Ret); + + return; + } + + private void IL_INSERT_FUNCTIONLIST() + { + Common.SendToDebug("Creating function list"); + + + string eventname = "GetFunctions"; + + Common.SendToDebug("Creating IL " + eventname); + // Define a private String field. + //FieldBuilder myField = myTypeBuilder.DefineField("EventList", typeof(String[]), FieldAttributes.Public); + + + //FieldBuilder mem = typeBuilder.DefineField("mem", typeof(Array), FieldAttributes.Private); + + + MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, + MethodAttributes.Public, + typeof (string[]), + null); + + //typeBuilder.DefineMethodOverride(methodBuilder, + // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); + + ILGenerator il = methodBuilder.GetILGenerator(); + + + // IL_INSERT_TRY(il, eventname); + + // // Push string to stack + // il.Emit(OpCodes.Ldstr, "Inside " + eventname); + + //// Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); + //il.Emit(OpCodes.Call, typeof(Console).GetMethod + // ("WriteLine", new Type[] { typeof(string) })); + + //initIL.Emit(OpCodes.Newobj, typeof(string[])); + + //string[] MyArray = new string[2] { "TestItem1" , "TestItem2" }; + + ////il.Emit(OpCodes.Ldarg_0); + + il.DeclareLocal(typeof (string[])); + + ////il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldc_I4, EventList.Count); // Specify array length + il.Emit(OpCodes.Newarr, typeof (String)); // create new string array + il.Emit(OpCodes.Stloc_0); // Store array as local variable 0 in stack + ////SetFunctionList + + for (int lv = 0; lv < EventList.Count; lv++) + { + il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack + il.Emit(OpCodes.Ldc_I4, lv); // Push index position + il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value + il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value + + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value + //il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("AddFunction", new Type[] { typeof(string) })); + } + + + // IL_INSERT_END_TRY(il, eventname); + + + il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack + // il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("SetFunctionList", new Type[] { typeof(Array) })); + + il.Emit(OpCodes.Ret); // Return + } + + + private void IL_INSERT_TRY(ILGenerator il, string eventname) + { + /* + * CLR TRY + */ + //Common.SendToDebug("CLR:" + eventname + ":il.BeginExceptionBlock()"); + il.BeginExceptionBlock(); + + // Push "Hello World!" string to stack + //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); + //il.Emit(OpCodes.Ldstr, "Starting CLR dynamic execution of: " + eventname); + } + + private void IL_INSERT_END_TRY(ILGenerator il, string eventname) + { + /* + * CATCH + */ + Common.SendToDebug("CLR:" + eventname + ":il.BeginCatchBlock(typeof(Exception));"); + il.BeginCatchBlock(typeof (Exception)); + + // Push "Hello World!" string to stack + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); + il.Emit(OpCodes.Ldstr, "Execption executing dynamic CLR function " + eventname + ": "); + + //call void [mscorlib]System.Console::WriteLine(string) + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + il.Emit(OpCodes.Call, typeof (Console).GetMethod + ("Write", new Type[] {typeof (string)})); + + //callvirt instance string [mscorlib]System.Exception::get_Message() + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Callvirt..."); + il.Emit(OpCodes.Callvirt, typeof (Exception).GetMethod + ("get_Message")); + + //call void [mscorlib]System.Console::WriteLine(string) + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + il.Emit(OpCodes.Call, typeof (Console).GetMethod + ("WriteLine", new Type[] {typeof (string)})); + + /* + * CLR END TRY + */ + //Common.SendToDebug("CLR:" + eventname + ":il.EndExceptionBlock();"); + il.EndExceptionBlock(); + } + + private LSO_Struct.StaticBlock GetStaticBlock(long pos) + { + long FirstPos = fs.Position; + try + { + UInt32 position = (UInt32) pos; + // STATIC BLOCK + Common.SendToDebug("Reading STATIC BLOCK at: " + position); + fs.Seek(position, SeekOrigin.Begin); + + if (StaticBlocks.ContainsKey(position) == true) + { + Common.SendToDebug("Found cached STATIC BLOCK"); + + + return StaticBlocks[pos]; + } + + //int StaticBlockCount = 0; + // Read function blocks until we hit GFR + //while (fs.Position < myHeader.GFR) + //{ + //StaticBlockCount++; + + //Common.SendToDebug("Reading Static Block at: " + position); + + //fs.Seek(myHeader.GVR, SeekOrigin.Begin); + LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); + myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); + myStaticBlock.ObjectType = br_read(1)[0]; + Common.SendToDebug("Static Block ObjectType: " + + ((LSO_Enums.Variable_Type_Codes) myStaticBlock.ObjectType).ToString()); + myStaticBlock.Unknown = br_read(1)[0]; + // Size of datatype varies + if (myStaticBlock.ObjectType != 0) + myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); + + StaticBlocks.Add(position, myStaticBlock); + //} + Common.SendToDebug("Done reading Static Block."); + return myStaticBlock; + } + finally + { + // Go back to original read pos + fs.Seek(FirstPos, SeekOrigin.Begin); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Struct.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Struct.cs new file mode 100644 index 0000000000..b38b0991bb --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSO/LSO_Struct.cs @@ -0,0 +1,143 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO +{ + internal static class LSO_Struct + { + public struct Header + { + public UInt32 TM; + public UInt32 IP; + public UInt32 VN; + public UInt32 BP; + public UInt32 SP; + public UInt32 HR; + public UInt32 HP; + public UInt32 CS; + public UInt32 NS; + public UInt32 CE; + public UInt32 IE; + public UInt32 ER; + public UInt32 FR; + public UInt32 SLR; + public UInt32 GVR; + public UInt32 GFR; + public UInt32 PR; + public UInt32 ESR; + public UInt32 SR; + public UInt64 NCE; + public UInt64 NIE; + public UInt64 NER; + } + + public struct StaticBlock + { + public UInt32 Static_Chunk_Header_Size; + public byte ObjectType; + public byte Unknown; + public byte[] BlockVariable; + } + + /* Not actually a structure + public struct StaticBlockVariable + { + public UInt32 Integer1; + public UInt32 Float1; + public UInt32 HeapPointer_String; + public UInt32 HeapPointer_Key; + public byte[] Vector_12; + public byte[] Rotation_16; + public UInt32 Pointer_List_Structure; + } */ + + public struct HeapBlock + { + public Int32 DataBlockSize; + public byte ObjectType; + public UInt16 ReferenceCount; + public byte[] Data; + } + + public struct StateFrameBlock + { + public UInt32 StateCount; + public StatePointerBlock[] StatePointer; + } + + public struct StatePointerBlock + { + public UInt32 Location; + public BitArray EventMask; + public StateBlock StateBlock; + } + + public struct StateBlock + { + public UInt32 StartPos; + public UInt32 EndPos; + public UInt32 HeaderSize; + public byte Unknown; + public StateBlockHandler[] StateBlockHandlers; + } + + public struct StateBlockHandler + { + public UInt32 CodeChunkPointer; + public UInt32 CallFrameSize; + } + + public struct FunctionBlock + { + public UInt32 FunctionCount; + public UInt32[] CodeChunkPointer; + } + + public struct CodeChunk + { + public UInt32 CodeChunkHeaderSize; + public string Comment; + public List CodeChunkArguments; + public byte EndMarker; + public byte ReturnTypePos; + public StaticBlock ReturnType; + } + + public struct CodeChunkArgument + { + public byte FunctionReturnTypePos; + public byte NullString; + public StaticBlock FunctionReturnType; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/TempDotNetMicroThreadingCodeInjector.cs b/OpenSim/Region/ScriptEngine/LSOEngine/LSOScript.cs similarity index 53% rename from OpenSim/Region/ScriptEngine/DotNetEngine/TempDotNetMicroThreadingCodeInjector.cs rename to OpenSim/Region/ScriptEngine/LSOEngine/LSOScript.cs index 76d0361b1b..47dfff260e 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/TempDotNetMicroThreadingCodeInjector.cs +++ b/OpenSim/Region/ScriptEngine/LSOEngine/LSOScript.cs @@ -1,69 +1,50 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.IO; -using Rail.Reflect; -using Rail.Transformation; - -namespace OpenSim.Region.ScriptEngine.DotNetEngine -{ - /// - /// Tedds Sandbox for RAIL/microtrheading. This class is only for testing purposes! - /// Its offspring will be the actual implementation. - /// - internal class TempDotNetMicroThreadingCodeInjector - { - public static string TestFix(string FileName) - { - string ret = Path.GetFileNameWithoutExtension(FileName + "_fixed.dll"); - - Console.WriteLine("Loading: \"" + FileName + "\""); - RAssemblyDef rAssembly = RAssemblyDef.LoadAssembly(FileName); - - - //Get the type of the method to copy from assembly Teste2.exe to assembly Teste.exe - RTypeDef type = (RTypeDef) rAssembly.RModuleDef.GetType("SecondLife.Script"); - - //Get the methods in the type - RMethod[] m = type.GetMethods(); - - //Create a MethodPrologueAdder visitor object with the method to add - //and with the flag that enables local variable creation set to true - MethodPrologueAdder mpa = new MethodPrologueAdder((RMethodDef) m[0], true); - - //Apply the changes to the assembly - rAssembly.Accept(mpa); - - //Save the new assembly - rAssembly.SaveAssembly(ret); - - return ret; - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using OpenSim.Region.ScriptEngine.LSOEngine.LSO; + +namespace OpenSim.Region.ScriptEngine.LSOEngine +{ + /// + /// This class encapsulated an LSO file and contains execution-specific data + /// + public class LSOScript + { + private byte[] LSOCode = new byte[1024 * 16]; // Contains the LSO-file + //private System.IO.MemoryStream LSOCode = new MemoryStream(1024 * 16); + + public void Execute(LSO_Enums.Event_Mask_Values Event, params object[] param) + { + + } + } +} diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/LSOEngine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..763a7598df --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/Properties/AssemblyInfo.cs @@ -0,0 +1,66 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.LSOEngine")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly: AssemblyProduct("OpenSim.Region.ScriptEngine.LSOEngine")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2008")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly : ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly : Guid("2842257e-6fde-4460-9368-4cde57fa9cc4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs new file mode 100644 index 0000000000..883ba8a486 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/ScriptEngine.cs @@ -0,0 +1,61 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; +using EventManager = OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.EventManager; +using ScriptManager=OpenSim.Region.ScriptEngine.LSOEngine.ScriptManager; + +namespace OpenSim.Region.ScriptEngine.LSOEngine +{ + [Serializable] + public class ScriptEngine : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptEngine + { + // We need to override a few things for our DotNetEngine + public override void Initialise(Scene scene, IConfigSource config) + { + InitializeEngine(scene, config, true, GetScriptManager()); + } + + public override OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager _GetScriptManager() + { + return new ScriptManager(this); + } + + public override string ScriptEngineName + { + get { return "ScriptEngine.LSOEngine"; } + } + + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs new file mode 100644 index 0000000000..4657e5caf2 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/LSOEngine/ScriptManager.cs @@ -0,0 +1,160 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; + +namespace OpenSim.Region.ScriptEngine.LSOEngine +{ + public class ScriptManager : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager + { + public ScriptManager(Common.ScriptEngineBase.ScriptEngine scriptEngine) + : base(scriptEngine) + { + base.m_scriptEngine = scriptEngine; + + } + + // KEEP TRACK OF SCRIPTS + //internal Dictionary> Scripts = new Dictionary>(); + // LOAD SCRIPT + // UNLOAD SCRIPT + // PROVIDE SCRIPT WITH ITS INTERFACE TO OpenSim + + public override void _StartScript(uint localID, LLUUID itemID, string Script) + { + //IScriptHost root = host.GetRoot(); + Console.WriteLine("ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID); + + // We will initialize and start the script. + // It will be up to the script itself to hook up the correct events. + string ScriptSource = String.Empty; + + SceneObjectPart m_host = World.GetSceneObjectPart(localID); + + try + { + // Compile (We assume LSL) + //ScriptSource = LSLCompiler.CompileFromLSLText(Script); + +#if DEBUG + long before; + before = GC.GetTotalMemory(true); +#endif + + IScript CompiledScript; + CompiledScript = m_scriptEngine.m_AppDomainManager.LoadScript(ScriptSource); + +#if DEBUG + Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before); +#endif + + CompiledScript.Source = ScriptSource; + // Add it to our script memstruct + SetScript(localID, itemID, CompiledScript); + + // We need to give (untrusted) assembly a private instance of BuiltIns + // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. + + + LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(m_scriptEngine, m_host, localID, itemID); + + // Start the script - giving it BuiltIns + CompiledScript.Start(LSLB); + + // Fire the first start-event + m_scriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_entry", EventQueueManager.llDetectNull, new object[] { }); + } + catch (Exception e) // LEGIT - User Script Compilation + { + //m_scriptEngine.Log.Error("[ScriptEngine]: Error compiling script: " + e.ToString()); + try + { + // DISPLAY ERROR INWORLD + string text = "Error compiling script:\r\n" + e.Message.ToString(); + if (text.Length > 1500) + text = text.Substring(0, 1500); + World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, + m_host.Name, m_host.UUID); + } + catch (Exception e2) // LEGIT - User Scripting + { + m_scriptEngine.Log.Error("[ScriptEngine]: Error displaying error in-world: " + e2.ToString()); + m_scriptEngine.Log.Error("[ScriptEngine]: " + + "Errormessage: Error compiling script:\r\n" + e.Message.ToString()); + } + } + } + + public override void _StopScript(uint localID, LLUUID itemID) + { + // Stop script + Console.WriteLine("Stop script localID: " + localID + " LLUID: " + itemID.ToString()); + + // Stop long command on script + m_scriptEngine.m_ASYNCLSLCommandManager.RemoveScript(localID, itemID); + + IScript LSLBC = GetScript(localID, itemID); + if (LSLBC == null) + return; + + // TEMP: First serialize it + //GetSerializedScript(localID, itemID); + + try + { + // Get AppDomain + AppDomain ad = LSLBC.Exec.GetAppDomain(); + // Tell script not to accept new requests + GetScript(localID, itemID).Exec.StopScript(); + // Remove from internal structure + RemoveScript(localID, itemID); + // Tell AppDomain that we have stopped script + m_scriptEngine.m_AppDomainManager.StopScript(ad); + } + catch (Exception e) // LEGIT - Problems caused by User Scripting + { + Console.WriteLine("Exception stopping script localID: " + localID + " LLUID: " + itemID.ToString() + + ": " + e.ToString()); + } + } + + public override void Initialize() + { + } + } +} diff --git a/OpenSim/Region/ScriptEngine/RemoteServer/Common.cs b/OpenSim/Region/ScriptEngine/RemoteServer/Common.cs index 906c157fa2..e65b8ffaf9 100644 --- a/OpenSim/Region/ScriptEngine/RemoteServer/Common.cs +++ b/OpenSim/Region/ScriptEngine/RemoteServer/Common.cs @@ -1,57 +1,58 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -namespace OpenSim.Region.ScriptEngine.RemoteServer -{ - public static class Common - { - public static bool debug = true; - public static ScriptEngine mySE; - - // This class just contains some static log stuff used for debugging. - - //public delegate void SendToDebugEventDelegate(string Message); - //public delegate void SendToLogEventDelegate(string Message); - //static public event SendToDebugEventDelegate SendToDebugEvent; - //static public event SendToLogEventDelegate SendToLogEvent; - - public static void SendToDebug(string Message) - { - //if (Debug == true) - mySE.Log.Verbose("ScriptEngine", "Debug: " + Message); - //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); - } - - public static void SendToLog(string Message) - { - //if (Debug == true) - mySE.Log.Verbose("ScriptEngine", "LOG: " + Message); - //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); - } - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ + +namespace OpenSim.Region.ScriptEngine.RemoteServer +{ + public static class Common + { + public static bool debug = true; + public static ScriptEngine mySE; + + // This class just contains some static log stuff used for debugging. + + //public delegate void SendToDebugEventDelegate(string Message); + //public delegate void SendToLogEventDelegate(string Message); + //static public event SendToDebugEventDelegate SendToDebugEvent; + //static public event SendToLogEventDelegate SendToLogEvent; + + public static void SendToDebug(string Message) + { + //if (Debug == true) + mySE.Log.Info("[ScriptEngine]: Debug: " + Message); + //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + + public static void SendToLog(string Message) + { + //if (Debug == true) + mySE.Log.Info("[ScriptEngine]: LOG: " + Message); + //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/RemoteServer/EventManager.cs b/OpenSim/Region/ScriptEngine/RemoteServer/EventManager.cs index 8555c8143a..971982caf9 100644 --- a/OpenSim/Region/ScriptEngine/RemoteServer/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/RemoteServer/EventManager.cs @@ -1,242 +1,263 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -using System; -using libsecondlife; -using OpenSim.Framework; -using OpenSim.Region.ScriptEngine.Common; - -namespace OpenSim.Region.ScriptEngine.RemoteServer -{ - /// - /// Handles events from OpenSim. Uses RemoteServer to send commands. - /// - [Serializable] - internal class EventManager - { - - System.Collections.Generic.Dictionary remoteScript = new System.Collections.Generic.Dictionary(); - - - private ScriptEngine myScriptEngine; - public EventManager(ScriptEngine _ScriptEngine) - { - myScriptEngine = _ScriptEngine; - - myScriptEngine.Log.Verbose("RemoteEngine", "Hooking up to server events"); - //myScriptEngine.World.EventManager.OnObjectGrab += touch_start; - myScriptEngine.World.EventManager.OnRezScript += OnRezScript; - //myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; - - - } - - - public void OnRezScript(uint localID, LLUUID itemID, string script) - { - // WE ARE CREATING A NEW SCRIPT ... CREATE SCRIPT, GET A REMOTEID THAT WE MAP FROM LOCALID - myScriptEngine.Log.Verbose("RemoteEngine", "Creating new script (with connection)"); - ScriptServerInterfaces.ServerRemotingObject obj = myScriptEngine.m_RemoteServer.Connect("localhost", 1234); - - remoteScript.Add(localID, obj); - //remoteScript[localID].Events.OnRezScript(localID, itemID, script); - - } - - public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) - { - //remoteScript[localID].Events.touch_start(localID, offsetPos, remoteClient); - } - - - - // PLACEHOLDERS -- CODE WILL CHANGE! - - - //public void OnRemoveScript(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.OnRemoveScript(localID, itemID); - //} - - //public void state_exit(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.state_exit(localID, itemID); - //} - - //public void touch(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.touch(localID, itemID); - //} - - //public void touch_end(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.touch_end(localID, itemID); - //} - - //public void collision_start(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.collision_start(localID, itemID); - //} - - //public void collision(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.collision(localID, itemID); - //} - - //public void collision_end(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.collision_end(localID, itemID); - //} - - //public void land_collision_start(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.land_collision_start(localID, itemID); - //} - - //public void land_collision(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.land_collision(localID, itemID); - //} - - //public void land_collision_end(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.land_collision_end(localID, itemID); - //} - - //public void timer(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.timer(localID, itemID); - //} - - //public void listen(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.listen(localID, itemID); - //} - - //public void on_rez(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.on_rez(localID, itemID); - //} - - //public void sensor(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.sensor(localID, itemID); - //} - - //public void no_sensor(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.no_sensor(localID, itemID); - //} - - //public void control(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.control(localID, itemID); - //} - - //public void money(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.money(localID, itemID); - //} - - //public void email(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.email(localID, itemID); - //} - - //public void at_target(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.at_target(localID, itemID); - //} - - //public void not_at_target(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.not_at_target(localID, itemID); - //} - - //public void at_rot_target(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.at_rot_target(localID, itemID); - //} - - //public void not_at_rot_target(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.not_at_rot_target(localID, itemID); - //} - - //public void run_time_permissions(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.run_time_permissions(localID, itemID); - //} - - //public void changed(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.changed(localID, itemID); - //} - - //public void attach(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.attach(localID, itemID); - //} - - //public void dataserver(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.dataserver(localID, itemID); - //} - - //public void link_message(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.link_message(localID, itemID); - //} - - //public void moving_start(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.moving_start(localID, itemID); - //} - - //public void moving_end(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.moving_end(localID, itemID); - //} - - //public void object_rez(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.object_rez(localID, itemID); - //} - - //public void remote_data(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.remote_data(localID, itemID); - //} - - //public void http_response(uint localID, LLUUID itemID) - //{ - // remoteScript[localID].Events.http_response(localID, itemID); - //} - - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.ScriptEngine.Common; +using OpenSim.Region.ScriptEngine.Common.TRPC; + +namespace OpenSim.Region.ScriptEngine.RemoteServer +{ + /// + /// Handles events from OpenSim. Uses RemoteServer to send commands. + /// + [Serializable] + internal class EventManager + { + System.Collections.Generic.Dictionary remoteScript = new System.Collections.Generic.Dictionary(); + TCPClient m_TCPClient; + TRPC_Remote RPC; + int myScriptServerID; + + string remoteHost = "127.0.0.1"; + int remotePort = 8010; + + private ScriptEngine myScriptEngine; + public EventManager(ScriptEngine _ScriptEngine) + { + myScriptEngine = _ScriptEngine; + + m_TCPClient = new TCPClient(); + RPC = new TRPC_Remote(m_TCPClient); + RPC.ReceiveCommand += new TRPC_Remote.ReceiveCommandDelegate(RPC_ReceiveCommand); + myScriptServerID = m_TCPClient.ConnectAndReturnID(remoteHost, remotePort); + + myScriptEngine.Log.Info("[RemoteEngine]: Hooking up to server events"); + //myScriptEngine.World.EventManager.OnObjectGrab += touch_start; + myScriptEngine.World.EventManager.OnRezScript += OnRezScript; + //myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; + } + + void RPC_ReceiveCommand(int ID, string Command, params object[] p) + { + myScriptEngine.Log.Info("[REMOTESERVER]: Received command: '" + Command + "'"); + if (p != null) + { + for (int i = 0; i < p.Length; i++) + { + myScriptEngine.Log.Info("[REMOTESERVER]: Param " + i + ": " + p[i].ToString()); + } + } + } + + public void OnRezScript(uint localID, LLUUID itemID, string script) + { + // WE ARE CREATING A NEW SCRIPT ... CREATE SCRIPT, GET A REMOTEID THAT WE MAP FROM LOCALID + myScriptEngine.Log.Info("[RemoteEngine]: Creating new script (with connection)"); + + // Temp for now: We have one connection only - this is hardcoded in myScriptServerID + RPC.SendCommand(myScriptServerID, "OnRezScript", localID, itemID.ToString(), script); + + //ScriptServerInterfaces.ServerRemotingObject obj = myScriptEngine.m_RemoteServer.Connect("localhost", 1234); + //remoteScript.Add(localID, obj); + //remoteScript[localID].Events().OnRezScript(localID, itemID, script); + } + + public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) + { + //remoteScript[localID].Events.touch_start(localID, offsetPos, remoteClient); + RPC.SendCommand(myScriptServerID, "touch_start", offsetPos, "How to transfer IClientAPI?"); + } + + + // PLACEHOLDERS -- CODE WILL CHANGE! + + + //public void OnRemoveScript(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.OnRemoveScript(localID, itemID); + //} + + //public void state_exit(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.state_exit(localID, itemID); + //} + + //public void touch(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.touch(localID, itemID); + //} + + //public void touch_end(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.touch_end(localID, itemID); + //} + + //public void collision_start(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.collision_start(localID, itemID); + //} + + //public void collision(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.collision(localID, itemID); + //} + + //public void collision_end(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.collision_end(localID, itemID); + //} + + //public void land_collision_start(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.land_collision_start(localID, itemID); + //} + + //public void land_collision(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.land_collision(localID, itemID); + //} + + //public void land_collision_end(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.land_collision_end(localID, itemID); + //} + + //public void timer(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.timer(localID, itemID); + //} + + //public void listen(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.listen(localID, itemID); + //} + + //public void on_rez(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.on_rez(localID, itemID); + //} + + //public void sensor(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.sensor(localID, itemID); + //} + + //public void no_sensor(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.no_sensor(localID, itemID); + //} + + //public void control(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.control(localID, itemID); + //} + + //public void money(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.money(localID, itemID); + //} + + //public void email(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.email(localID, itemID); + //} + + //public void at_target(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.at_target(localID, itemID); + //} + + //public void not_at_target(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.not_at_target(localID, itemID); + //} + + //public void at_rot_target(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.at_rot_target(localID, itemID); + //} + + //public void not_at_rot_target(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.not_at_rot_target(localID, itemID); + //} + + //public void run_time_permissions(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.run_time_permissions(localID, itemID); + //} + + //public void changed(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.changed(localID, itemID); + //} + + //public void attach(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.attach(localID, itemID); + //} + + //public void dataserver(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.dataserver(localID, itemID); + //} + + //public void link_message(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.link_message(localID, itemID); + //} + + //public void moving_start(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.moving_start(localID, itemID); + //} + + //public void moving_end(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.moving_end(localID, itemID); + //} + + //public void object_rez(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.object_rez(localID, itemID); + //} + + //public void remote_data(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.remote_data(localID, itemID); + //} + + //public void http_response(uint localID, LLUUID itemID) + //{ + // remoteScript[localID].Events.http_response(localID, itemID); + //} + } +} diff --git a/OpenSim/Region/ScriptEngine/RemoteServer/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/RemoteServer/Properties/AssemblyInfo.cs index b01356296c..4efc6d51c6 100644 --- a/OpenSim/Region/ScriptEngine/RemoteServer/Properties/AssemblyInfo.cs +++ b/OpenSim/Region/ScriptEngine/RemoteServer/Properties/AssemblyInfo.cs @@ -1,38 +1,66 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly : AssemblyTitle("OpenSim.Region.ScriptEngine.RemoteServer")] -[assembly : AssemblyDescription("")] -[assembly : AssemblyConfiguration("")] -[assembly : AssemblyCompany("")] -[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.RemoteServer")] -[assembly : AssemblyCopyright("Copyright © 2007")] -[assembly : AssemblyTrademark("")] -[assembly : AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly : ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly : Guid("2842257e-6fde-4460-9368-4cde57fa9cc4")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly : AssemblyVersion("1.0.0.0")] -[assembly : AssemblyFileVersion("1.0.0.0")] \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly : AssemblyTitle("OpenSim.Region.ScriptEngine.RemoteServer")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("")] +[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.RemoteServer")] +[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2008")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly : ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly : Guid("2842257e-6fde-4460-9368-4cde57fa9cc4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("1.0.0.0")] +[assembly : AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/ScriptEngine/RemoteServer/RemoteServer.cs b/OpenSim/Region/ScriptEngine/RemoteServer/RemoteServer.cs index 8f1337670b..ba678df8a8 100644 --- a/OpenSim/Region/ScriptEngine/RemoteServer/RemoteServer.cs +++ b/OpenSim/Region/ScriptEngine/RemoteServer/RemoteServer.cs @@ -1,59 +1,83 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.Remoting; -using System.Runtime.Remoting.Channels; -using System.Runtime.Remoting.Channels.Tcp; -using OpenSim.Region.ScriptEngine.Common; - -namespace OpenSim.Region.ScriptEngine.RemoteServer -{ - class RemoteServer - { - // Handles connections to servers - // Create and returns server object - - public ScriptServerInterfaces.ServerRemotingObject Connect(string hostname, int port) - { - // Create a channel for communicating w/ the remote object - // Notice no port is specified on the client - TcpChannel chan = new TcpChannel(); - try - { - ChannelServices.RegisterChannel(chan, true); - } - catch (System.Runtime.Remoting.RemotingException) - { - System.Console.WriteLine("Error: tcp already registered, RemoteServer.cs in OpenSim.Region.ScriptEngine.RemoteServer line 24"); - } - try - { - - // Create an instance of the remote object - ScriptServerInterfaces.ServerRemotingObject obj = (ScriptServerInterfaces.ServerRemotingObject)Activator.GetObject( - typeof(ScriptServerInterfaces.ServerRemotingObject), - "tcp://" + hostname + ":" + port + "/DotNetEngine"); - - // Use the object - if (obj.Equals(null)) - { - System.Console.WriteLine("Error: unable to locate server"); - } - else - { - return obj; - } - } - catch (System.Net.Sockets.SocketException) - { - System.Console.WriteLine("Error: unable to connect to server"); - } - catch (System.Runtime.Remoting.RemotingException) - { - System.Console.WriteLine("Error: unable to connect to server"); - } - return null; - - } - } -} +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; +using OpenSim.Region.ScriptEngine.Common; + +namespace OpenSim.Region.ScriptEngine.RemoteServer +{ + class RemoteServer + { + // Handles connections to servers + // Create and returns server object + + public RemoteServer() + { + TcpChannel chan = new TcpChannel(); + ChannelServices.RegisterChannel(chan, true); + } + + public ScriptServerInterfaces.ServerRemotingObject Connect(string hostname, int port) + { + // Create a channel for communicating w/ the remote object + // Notice no port is specified on the client + + try + { + // Create an instance of the remote object + ScriptServerInterfaces.ServerRemotingObject obj = (ScriptServerInterfaces.ServerRemotingObject)Activator.GetObject( + typeof(ScriptServerInterfaces.ServerRemotingObject), + "tcp://" + hostname + ":" + port + "/DotNetEngine"); + + // Use the object + if (obj.Equals(null)) + { + System.Console.WriteLine("Error: unable to locate server"); + } + else + { + return obj; + } + } + catch (System.Net.Sockets.SocketException) + { + System.Console.WriteLine("Error: unable to connect to server"); + } + catch (System.Runtime.Remoting.RemotingException) + { + System.Console.WriteLine("Error: unable to connect to server"); + } + return null; + } + } +} diff --git a/OpenSim/Region/ScriptEngine/RemoteServer/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/RemoteServer/ScriptEngine.cs index 74d84a59f3..8d27251f27 100644 --- a/OpenSim/Region/ScriptEngine/RemoteServer/ScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/RemoteServer/ScriptEngine.cs @@ -1,106 +1,104 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -/* Original code: Tedd Hansen */ -using System; -using Nini.Config; -using OpenSim.Framework.Console; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.ScriptEngine.RemoteServer -{ - /// - /// This is the root object for RemoteServer. Objects access each other trough this class. - /// - /// - [Serializable] - public class ScriptEngine : IRegionModule - { - internal Scene World; - internal EventManager m_EventManager; // Handles and queues incoming events from OpenSim - internal RemoteServer m_RemoteServer; // Handles connections to remote servers - - private LogBase m_log; - - public ScriptEngine() - { - Common.mySE = this; - } - - public LogBase Log - { - get { return m_log; } - } - - public void InitializeEngine(Scene Sceneworld, LogBase logger) - { - World = Sceneworld; - m_log = logger; - - Log.Verbose("ScriptEngine", "RemoteEngine (Remote Script Server) initializing"); - // Create all objects we'll be using - m_EventManager = new EventManager(this); - m_RemoteServer = new RemoteServer(); - m_RemoteServer.Connect("localhost", 1234); - } - - public void Shutdown() - { - // We are shutting down - } - - - #region IRegionModule - - public void Initialise(Scene scene, IConfigSource config) - { - InitializeEngine(scene, MainLog.Instance); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "RemoteServerScriptingModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - } -} \ No newline at end of file +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ScriptEngine.RemoteServer +{ + /// + /// This is the root object for RemoteServer. Objects access each other trough this class. + /// + /// + [Serializable] + public class ScriptEngine : IRegionModule + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + internal Scene World; + internal EventManager m_EventManager; // Handles and queues incoming events from OpenSim + internal RemoteServer m_RemoteServer; // Handles connections to remote servers + + public ScriptEngine() + { + Common.mySE = this; + } + + public log4net.ILog Log + { + get { return m_log; } + } + + public void InitializeEngine(Scene Sceneworld) + { + World = Sceneworld; + + m_log.Info("[ScriptEngine]: RemoteEngine (Remote Script Server) initializing"); + // Create all objects we'll be using + m_EventManager = new EventManager(this); + m_RemoteServer = new RemoteServer(); + m_RemoteServer.Connect("localhost", 1234); + } + + public void Shutdown() + { + // We are shutting down + } + + #region IRegionModule + + public void Initialise(Scene scene, IConfigSource config) + { + InitializeEngine(scene); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "RemoteServerScriptingModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + } +}