* Rex merge, remaining Region files.

* This is the last rex merge on /branches/afrisby-3/, all files have been merged, but it's highly unlikely it compiles.
afrisby-3
Adam Frisby 2008-02-25 18:02:56 +00:00
parent 4853884c30
commit 0c77413d1f
71 changed files with 26717 additions and 17809 deletions

View File

@ -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.*")]
[assembly : AssemblyVersion("1.0.*")]

View File

@ -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
{
/// <summary>
/// Will be the PhysX plugin but for now will be a very basic physics engine
/// </summary>
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<BasicActor> _actors = new List<BasicActor>();
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)
{
}
}
}
/*
* 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
{
/// <summary>
/// Will be the PhysX plugin but for now will be a very basic physics engine
/// </summary>
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<BasicActor> _actors = new List<BasicActor>();
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()
{
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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<IntPtr> worldlock = new List<IntPtr>();
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);
}
}
}
}

View File

@ -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<uint> m_objCollisionList;
public CollisionEventUpdate(uint localID, int colliderType, bool startOrEnd, List<uint> 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;
}
}
}
/*
* 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<uint> m_objCollisionList;
public CollisionEventUpdate(uint localID, int colliderType, bool startOrEnd, List<uint> 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;
}
}
}

View File

@ -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
{
/// <summary>
/// Description of MyClass.
/// </summary>
public class PhysicsPluginManager
{
private Dictionary<string, IPhysicsPlugin> _PhysPlugins = new Dictionary<string, IPhysicsPlugin>();
private Dictionary<string, IMeshingPlugin> _MeshPlugins = new Dictionary<string, IMeshingPlugin>();
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
{
/// <summary>
/// Description of MyClass.
/// </summary>
public class PhysicsPluginManager
{
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Dictionary<string, IPhysicsPlugin> _PhysPlugins = new Dictionary<string, IPhysicsPlugin>();
private Dictionary<string, IMeshingPlugin> _MeshPlugins = new Dictionary<string, IMeshingPlugin>();
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();
}
}
}
}
//---
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();
}
}

View File

@ -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; }
}
}
}
}
/*
* 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()
{
}
}
}
}

View File

@ -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 { } }
}
}

View File

@ -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;
}
}
}
/*
* 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 + ">";
}
/// <summary>
/// These routines are the easiest way to store XYZ values in an LLVector3 without requiring 3 calls.
/// </summary>
/// <returns></returns>
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;
}
}
}

View File

@ -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;
}
}
}
/*
* 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;
}
}
}

View File

@ -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;
}
}
}
/*
* 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;
}
}
}

View File

@ -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<Vertex>
{
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<Simplex> GetSimplices()
{
List<Simplex> result = new List<Simplex>();
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;
}
}
/*
* 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<Vertex>
{
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<Simplex> GetSimplices()
{
List<Simplex> result = new List<Simplex>();
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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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<Vertex> vertices = new List<Vertex>();
private List<Vertex> holeVertices = new List<Vertex>(); // 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<Vertex> getVertices()
{
List<Vertex> newVertices = new List<Vertex>();
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<Simplex> 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<Simplex> buildSimplexList()
{
List<Simplex> result = new List<Simplex>();
// 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<Simplex> 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;
}
}
}
/*
* 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<Vertex> vertices = new List<Vertex>();
private List<Vertex> holeVertices = new List<Vertex>(); // 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<Vertex> getVertices()
{
List<Vertex> newVertices = new List<Vertex>();
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<Simplex> 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<Simplex> buildSimplexList()
{
List<Simplex> result = new List<Simplex>();
// 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<Simplex> 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;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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.*")]
[assembly : AssemblyVersion("1.0.*")]

File diff suppressed because it is too large Load Diff

View File

@ -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.*")]
[assembly : AssemblyVersion("1.0.*")]

File diff suppressed because it is too large Load Diff

View File

@ -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<string, MethodInfo> Events = new Dictionary<string, MethodInfo>();
private bool m_Running = true;
//private List<IScript> Scripts = new List<IScript>();
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;
}
}
}
/*
* 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<string, MethodInfo> Events = new Dictionary<string, MethodInfo>();
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);
}
}
}

View File

@ -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
{
/// <summary>
/// Contains the script to execute functions in.
/// </summary>
protected IScript m_Script;
/// <summary>
/// If set to False events will not be executed.
/// </summary>
protected bool m_Running = true;
/// <summary>
/// Create a new instance of ExecutorBase
/// </summary>
/// <param name="Script"></param>
public ExecutorBase(IScript Script)
{
m_Script = Script;
}
/// <summary>
/// Make sure our object does not timeout when in AppDomain. (Called by ILease base class)
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// Get current AppDomain
/// </summary>
/// <returns>Current AppDomain</returns>
public AppDomain GetAppDomain()
{
return AppDomain.CurrentDomain;
}
/// <summary>
/// Execute a specific function/event in script.
/// </summary>
/// <param name="FunctionName">Name of function to execute</param>
/// <param name="args">Arguments to pass to function</param>
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);
/// <summary>
/// Stop script from running. Event execution will be ignored.
/// </summary>
public void StopScript()
{
m_Running = false;
}
}
}

View File

@ -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; }
}
}
/*
* 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; }
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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")]
/*
* 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")]

View File

@ -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;
/// <summary>
/// Internal list of all AppDomains
/// </summary>
private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
/// <summary>
/// Structure to keep track of data around AppDomain
/// </summary>
private class AppDomainStructure
{
/// <summary>
/// The AppDomain itself
/// </summary>
public AppDomain CurrentAppDomain;
/// <summary>
/// Number of scripts loaded into AppDomain
/// </summary>
public int ScriptsLoaded;
/// <summary>
/// Number of dead scripts
/// </summary>
public int ScriptsWaitingUnload;
}
/// <summary>
/// Current AppDomain
/// </summary>
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;
}
/// <summary>
/// Find a free AppDomain, creating one if necessary
/// </summary>
/// <returns>Free AppDomain</returns>
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;
/// <summary>
/// Create and prepare a new AppDomain for scripts
/// </summary>
/// <returns>The new AppDomain</returns>
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;
}
/// <summary>
/// Unload appdomains that are full and have only dead scripts
/// </summary>
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;
}
/// <summary>
/// Increase "dead script" counter for an AppDomain
/// </summary>
/// <param name="ad"></param>
//[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
}
}
}
/*
* 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;
/// <summary>
/// Internal list of all AppDomains
/// </summary>
private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
/// <summary>
/// Structure to keep track of data around AppDomain
/// </summary>
private class AppDomainStructure
{
/// <summary>
/// The AppDomain itself
/// </summary>
public AppDomain CurrentAppDomain;
/// <summary>
/// Number of scripts loaded into AppDomain
/// </summary>
public int ScriptsLoaded;
/// <summary>
/// Number of dead scripts
/// </summary>
public int ScriptsWaitingUnload;
}
/// <summary>
/// Current AppDomain
/// </summary>
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);
}
/// <summary>
/// Find a free AppDomain, creating one if necessary
/// </summary>
/// <returns>Free AppDomain</returns>
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;
/// <summary>
/// Create and prepare a new AppDomain for scripts
/// </summary>
/// <returns>The new AppDomain</returns>
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;
}
/// <summary>
/// Unload appdomains that are full and have only dead scripts
/// </summary>
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;
}
/// <summary>
/// Increase "dead script" counter for an AppDomain
/// </summary>
/// <param name="ad"></param>
//[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
}
/// <summary>
/// If set to true then threads and stuff should try to make a graceful exit
/// </summary>
public bool PleaseShutdown
{
get { return _PleaseShutdown; }
set { _PleaseShutdown = value; }
}
private bool _PleaseShutdown = false;
}
}

View File

@ -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
{
/// <summary>
/// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
/// </summary>
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();
}
/// <summary>
/// Remove a specific script (and all its pending commands)
/// </summary>
/// <param name="localID"></param>
/// <param name="itemID"></param>
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<IHttpRequests>();
iHttpReq.StopHttpRequest(localID, itemID);
IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
comms.DeleteListener(itemID);
IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
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<TimerClass> Timers = new List<TimerClass>();
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<TimerClass> NewTimers = new List<TimerClass>();
//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<IHttpRequests>();
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<IXMLRPC>();
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<IWorldComm>();
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
/// <summary>
/// If set to true then threads and stuff should try to make a graceful exit
/// </summary>
public bool PleaseShutdown
{
get { return _PleaseShutdown; }
set { _PleaseShutdown = value; }
}
private bool _PleaseShutdown = false;
}
}

View File

@ -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);
}
}
}
/*
* 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);
}
}
}

View File

@ -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
{
/// <summary>
/// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
/// </summary>
[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
{
/// <summary>
/// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
/// </summary>
[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);
}
/// <summary>
/// If set to true then threads and stuff should try to make a graceful exit
/// </summary>
public bool PleaseShutdown
{
get { return _PleaseShutdown; }
set { _PleaseShutdown = value; }
}
private bool _PleaseShutdown = false;
}
}

View File

@ -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
{
/// <summary>
/// EventQueueManager handles event queues
/// Events are queued and executed in separate thread
/// </summary>
[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;
/// <summary>
/// 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.
/// </summary>
internal static List<EventQueueThreadClass> eventQueueThreads = new List<EventQueueThreadClass>(); // Thread pool that we work on
/// <summary>
/// Locking access to eventQueueThreads AND staticGlobalEventQueueThreads.
/// </summary>
// private object eventQueueThreadsLock = new object();
// Static objects for referencing the objects above if we don't have private threads:
//internal static List<EventQueueThreadClass> staticEventQueueThreads; // A static reference used if we don't use private threads
// internal static object staticEventQueueThreadsLock; // Statick lock object reference for same reason
/// <summary>
/// Global static list of all threads (classes) processing event queue -- used by max enforcment thread
/// </summary>
//private List<EventQueueThreadClass> staticGlobalEventQueueThreads = new List<EventQueueThreadClass>();
/// <summary>
/// Used internally to specify how many threads should exit gracefully
/// </summary>
public static int ThreadsToExit;
public static object ThreadsToExitLock = new object();
//public object queueLock = new object(); // Mutex lock object
/// <summary>
/// How many threads to process queue with
/// </summary>
internal static int numberOfThreads;
internal static int EventExecutionMaxQueueSize;
/// <summary>
/// Maximum time one function can use for execution before we perform a thread kill.
/// </summary>
private static int maxFunctionExecutionTimems
{
get { return (int)(maxFunctionExecutionTimens / 10000); }
set { maxFunctionExecutionTimens = value * 10000; }
}
/// <summary>
/// Contains nanoseconds version of maxFunctionExecutionTimems so that it matches time calculations better (performance reasons).
/// WARNING! ONLY UPDATE maxFunctionExecutionTimems, NEVER THIS DIRECTLY.
/// </summary>
public static long maxFunctionExecutionTimens;
/// <summary>
/// Enforce max execution time
/// </summary>
public static bool EnforceMaxExecutionTime;
/// <summary>
/// Kill script (unload) when it exceeds execution time
/// </summary>
private static bool KillScriptOnMaxFunctionExecutionTime;
/// <summary>
/// List of localID locks for mutex processing of script events
/// </summary>
private List<uint> objectLocks = new List<uint>();
private object tryLockLock = new object(); // Mutex lock object
/// <summary>
/// Queue containing events waiting to be executed
/// </summary>
public Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>();
#region " Queue structures "
/// <summary>
/// Queue item structure
/// </summary>
public struct QueueItemStruct
{
public uint localID;
public LLUUID itemID;
public string functionName;
public Queue_llDetectParams_Struct llDetectParams;
public object[] param;
}
/// <summary>
/// Shared empty llDetectNull
/// </summary>
public readonly static Queue_llDetectParams_Struct llDetectNull = new Queue_llDetectParams_Struct();
/// <summary>
/// Structure to hold data for llDetect* commands
/// </summary>
[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 "
/// <summary>
/// Try to get a mutex lock on localID
/// </summary>
/// <param name="localID"></param>
/// <returns></returns>
public bool TryLock(uint localID)
{
lock (tryLockLock)
{
if (objectLocks.Contains(localID) == true)
{
return false;
}
else
{
objectLocks.Add(localID);
return true;
}
}
}
/// <summary>
/// Release mutex lock on localID
/// </summary>
/// <param name="localID"></param>
public void ReleaseLock(uint localID)
{
lock (tryLockLock)
{
if (objectLocks.Contains(localID) == true)
{
objectLocks.Remove(localID);
}
}
}
#endregion
#region " Add events to execution queue "
/// <summary>
/// Add event to event execution queue
/// </summary>
/// <param name="localID">Region object ID</param>
/// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
/// <param name="param">Array of parameters to match event mask</param>
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<LLUUID, IScript>.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);
}
}
/// <summary>
/// Add event to event execution queue
/// </summary>
/// <param name="localID">Region object ID</param>
/// <param name="itemID">Region script ID</param>
/// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
/// <param name="param">Array of parameters to match event mask</param>
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 "
/// <summary>
/// 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
/// </summary>
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);
}
}
}
}
/// <summary>
/// Check if any thread class has been executing an event too long
/// </summary>
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
///// <summary>
///// If set to true then threads and stuff should try to make a graceful exit
///// </summary>
//public bool PleaseShutdown
//{
// get { return _PleaseShutdown; }
// set { _PleaseShutdown = value; }
//}
//private bool _PleaseShutdown = false;
}
}

View File

@ -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
{
/// <summary>
/// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class
/// </summary>
public class EventQueueThreadClass : iScriptEngineFunctionModule
{
/// <summary>
/// How many ms to sleep if queue is empty
/// </summary>
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;
}
/// <summary>
/// Start thread
/// </summary>
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;
/// <summary>
/// Queue processing thread loop
/// </summary>
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);
}
}
}
}
// }
}
///// <summary>
///// If set to true then threads and stuff should try to make a graceful exit
///// </summary>
//public bool PleaseShutdown
//{
// get { return _PleaseShutdown; }
// set { _PleaseShutdown = value; }
//}
//private bool _PleaseShutdown = false;
}
}

View File

@ -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
{
/// <summary>
/// This class does maintenance on script engine.
/// </summary>
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 "
/// <summary>
/// Maintenance thread. Enforcing max execution time for example.
/// </summary>
public Thread MaintenanceThreadThread;
/// <summary>
/// Starts maintenance thread
/// </summary>
private void StartMaintenanceThread()
{
if (MaintenanceThreadThread == null)
{
MaintenanceThreadThread = new Thread(MaintenanceLoop);
MaintenanceThreadThread.Name = "ScriptMaintenanceThread";
MaintenanceThreadThread.IsBackground = true;
MaintenanceThreadThread.Start();
OpenSim.Framework.ThreadTracker.Add(MaintenanceThreadThread);
}
}
/// <summary>
/// Stops maintenance thread
/// </summary>
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
/// <summary>
/// A thread should run in this loop and check all running scripts
/// </summary>
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
///// <summary>
///// If set to true then threads and stuff should try to make a graceful exit
///// </summary>
//public bool PleaseShutdown
//{
// get { return _PleaseShutdown; }
// set { _PleaseShutdown = value; }
//}
//private bool _PleaseShutdown = false;
}
}

View File

@ -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
{
/// <summary>
/// This is the root object for ScriptEngine. Objects access each other trough this class.
/// </summary>
///
[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<ScriptEngine> ScriptEngines = new List<ScriptEngine>();
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; }
/// <summary>
/// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes.
/// </summary>
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
}
}

View File

@ -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
{
/// <summary>
/// Loads scripts
/// Compiles them if necessary
/// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
/// </summary>
///
// 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<LUStruct> LUQueue = new Queue<LUStruct>();
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<string, Script<string, script>>
// IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
// Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
public Dictionary<uint, Dictionary<LLUUID, IScript>> Scripts =
new Dictionary<uint, Dictionary<LLUUID, IScript>>();
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();
/// <summary>
/// Fetches, loads and hooks up a script to an objects events
/// </summary>
/// <param name="itemID"></param>
/// <param name="localID"></param>
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);
}
/// <summary>
/// Disables and unloads a script
/// </summary>
/// <param name="localID"></param>
/// <param name="itemID"></param>
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
/// <summary>
/// Execute a LL-event-function in Script
/// </summary>
/// <param name="localID">Object the script is located in</param>
/// <param name="itemID">Script ID</param>
/// <param name="FunctionName">Name of function</param>
/// <param name="args">Arguments to pass to function</param>
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<LLUUID, IScript>.KeyCollection GetScriptKeys(uint localID)
{
if (Scripts.ContainsKey(localID) == false)
return null;
Dictionary<LLUUID, IScript> 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<LLUUID, IScript> 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<LLUUID, IScript>());
}
// Delete script if it exists
Dictionary<LLUUID, IScript> 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<LLUUID, IScript> 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
///// <summary>
///// If set to true then threads and stuff should try to make a graceful exit
///// </summary>
//public bool PleaseShutdown
//{
// get { return _PleaseShutdown; }
// set { _PleaseShutdown = value; }
//}
//private bool _PleaseShutdown = false;
}
}

View File

@ -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; }
}
}

View File

@ -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();
}
}
}

View File

@ -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
{
}
}

View File

@ -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<int, TCPSocket> Clients = new Dictionary<int, TCPSocket>();
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;
/// <summary>
/// Creates client connection
/// </summary>
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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
/// <summary>
/// Starts listening for new connections
/// </summary>
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);
}
/// <summary>
/// Stops listening for new connections
/// </summary>
public void StopListen()
{
server.Close();
server = null;
}
private readonly Dictionary<int, TCPSocket> Clients = new Dictionary<int, TCPSocket>();
private int ClientCount = 0;
public event TCPCommon.ClientConnectedDelegate ClientConnected;
public event TCPCommon.DataReceivedDelegate DataReceived;
public event TCPCommon.DataSentDelegate DataSent;
public event TCPCommon.CloseDelegate Close;
/// <summary>
/// Async callback for new connections
/// </summary>
/// <param name="ar"></param>
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);
}
}
}

View File

@ -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);
}
/// <summary>
/// Callback for successful receive (or connection close)
/// </summary>
/// <param name="ar"></param>
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);
}
/// <summary>
/// Callback for successful send
/// </summary>
/// <param name="ar"></param>
void asyncDataSent(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
int sent = client.EndSend(ar);
DataSent(ID, sent);
}
public void Disconnect()
{
Client.Close();
Close(ID);
}
}
}

View File

@ -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<string, Type> TypeDictionary = new Dictionary<string, Type>();
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<int, InQueueStruct> InQueue = new Dictionary<int, InQueueStruct>();
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);
}
}
}

View File

@ -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.");
}
}
/// <summary>
/// Converts script from LSL to CS and calls CompileFromCSText
/// </summary>
/// <param name="Script">LSL script</param>
/// <returns>Filename to .dll assembly</returns>
public string CompileFromLSLText(string Script)
{
if (Script.Substring(0, 4).ToLower() == "//c#")
{
return CompileFromCSText(Script);
}
else
{
return CompileFromCSText(LSL_Converter.Convert(Script));
}
}
/// <summary>
/// Compile CS script to .Net assembly (.dll)
/// </summary>
/// <param name="Script">CS script</param>
/// <returns>Filename to .dll assembly</returns>
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;
}
}
}
/*
* 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
}
/// <summary>
/// This contains number of lines WE use for header when compiling script. User will get error in line x-LinesToRemoveOnError when error occurs.
/// </summary>
public int LinesToRemoveOnError = 3;
private enumCompileType DefaultCompileLanguage;
private bool WriteScriptSourceToDebugFile;
private bool CompileWithDebugInformation;
private bool CleanUpOldScriptsOnStartup;
private System.Collections.Generic.Dictionary<string, Boolean> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
private System.Collections.Generic.Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(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
}
/// <summary>
/// Delete old script files
/// </summary>
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.");
// }
//}
/// <summary>
/// Converts script from LSL to CS and calls CompileFromCSText
/// </summary>
/// <param name="Script">LSL script</param>
/// <returns>Filename to .dll assembly</returns>
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;
}
/// <summary>
/// Compile .NET script to .Net assembly (.dll)
/// </summary>
/// <param name="Script">CS script</param>
/// <returns>Filename to .dll assembly</returns>
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;
}
}
}

View File

@ -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<string, string> dataTypes = new Dictionary<string, string>();
private Dictionary<string, string> quotes = new Dictionary<string, string>();
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,
@"(?<s1>(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?<s2>[^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" + "<STATE>" + "$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 <x,y,z> and <x,y,z,r>
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;
}
}
}
/*
* 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<string, string> dataTypes = new Dictionary<string, string>();
private Dictionary<string, string> quotes = new Dictionary<string, string>();
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,
@"(?<s1>(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?<s2>[^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" + "<STATE>" + "$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 <x,y,z> and <x,y,z,r>
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;
}
}
}

View File

@ -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
{
/// <summary>
/// EventQueueManager handles event queues
/// Events are queued and executed in separate thread
/// </summary>
[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.
//
/// <summary>
/// List of threads processing event queue
/// </summary>
private List<Thread> eventQueueThreads = new List<Thread>();
private object queueLock = new object(); // Mutex lock object
/// <summary>
/// How many ms to sleep if queue is empty
/// </summary>
private int nothingToDoSleepms = 50;
/// <summary>
/// How many threads to process queue with
/// </summary>
private int numberOfThreads = 2;
/// <summary>
/// Queue containing events waiting to be executed
/// </summary>
private Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>();
/// <summary>
/// Queue item structure
/// </summary>
private struct QueueItemStruct
{
public uint localID;
public LLUUID itemID;
public string functionName;
public object[] param;
}
/// <summary>
/// List of localID locks for mutex processing of script events
/// </summary>
private List<uint> objectLocks = new List<uint>();
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();
}
/// <summary>
/// Queue processing thread loop
/// </summary>
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);
}
}
/// <summary>
/// Try to get a mutex lock on localID
/// </summary>
/// <param name="localID"></param>
/// <returns></returns>
private bool TryLock(uint localID)
{
lock (tryLockLock)
{
if (objectLocks.Contains(localID) == true)
{
return false;
}
else
{
objectLocks.Add(localID);
return true;
}
}
}
/// <summary>
/// Release mutex lock on localID
/// </summary>
/// <param name="localID"></param>
private void ReleaseLock(uint localID)
{
lock (tryLockLock)
{
if (objectLocks.Contains(localID) == true)
{
objectLocks.Remove(localID);
}
}
}
/// <summary>
/// Add event to event execution queue
/// </summary>
/// <param name="localID"></param>
/// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
/// <param name="param">Array of parameters to match event mask</param>
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<LLUUID, LSL_BaseClass>.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);
}
}
/// <summary>
/// Add event to event execution queue
/// </summary>
/// <param name="localID"></param>
/// <param name="itemID"></param>
/// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
/// <param name="param">Array of parameters to match event mask</param>
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);
}
}
}
}

View File

@ -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
{
/// <summary>
/// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
/// </summary>
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);
}
}
/// <summary>
/// Remove a specific script (and all its pending commands)
/// </summary>
/// <param name="m_localID"></param>
/// <param name="m_itemID"></param>
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<IHttpRequests>();
iHttpReq.StopHttpRequest(localID, itemID);
}
#region TIMER
//
// TIMER
//
private class TimerClass
{
public uint localID;
public LLUUID itemID;
public double interval;
public DateTime next;
}
private List<TimerClass> Timers = new List<TimerClass>();
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<TimerClass> NewTimers = new List<TimerClass>();
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<IHttpRequests>();
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<IXMLRPC>();
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<IWorldComm>();
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
);
}
}
}
}

View File

@ -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")]
/*
* 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")]

View File

@ -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
{
/// <summary>
/// This is the root object for ScriptEngine. Objects access each other trough this class.
/// </summary>
///
[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
}
}
/*
* 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"; }
}
}
}

View File

@ -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
{
/// <summary>
/// Loads scripts
/// Compiles them if necessary
/// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
/// </summary>
///
// 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<LUStruct> LUQueue = new Queue<LUStruct>();
// 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<string, Script<string, script>>
// IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
// Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
internal Dictionary<uint, Dictionary<LLUUID, LSL_BaseClass>> Scripts =
new Dictionary<uint, Dictionary<LLUUID, LSL_BaseClass>>();
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<LLUUID, LSL_BaseClass>.KeyCollection GetScriptKeys(uint localID)
{
if (Scripts.ContainsKey(localID) == false)
return null;
Dictionary<LLUUID, LSL_BaseClass> 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<LLUUID, LSL_BaseClass> 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<LLUUID, LSL_BaseClass>());
}
// Delete script if it exists
Dictionary<LLUUID, LSL_BaseClass> 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<LLUUID, LSL_BaseClass> 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();
/// <summary>
/// Fetches, loads and hooks up a script to an objects events
/// </summary>
/// <param name="itemID"></param>
/// <param name="localID"></param>
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);
}
/// <summary>
/// Disables and unloads a script
/// </summary>
/// <param name="localID"></param>
/// <param name="itemID"></param>
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
/// <summary>
/// Execute a LL-event-function in Script
/// </summary>
/// <param name="localID">Object the script is located in</param>
/// <param name="itemID">Script ID</param>
/// <param name="FunctionName">Name of function</param>
/// <param name="args">Arguments to pass to function</param>
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
}
}
/*
* 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 <int id, whatever script>
//internal Dictionary<uint, Dictionary<LLUUID, LSL_BaseClass>> Scripts = new Dictionary<uint, Dictionary<LLUUID, LSL_BaseClass>>();
// 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());
}
}
}
}

View File

@ -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";
}
}
}

View File

@ -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<string> Functions = (System.Collections.Generic.List<string>)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
}
}

View File

@ -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;
}
}
}

View File

@ -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<object> s = new Stack<object>();
// // 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: <null>");
// }
// 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));
// }
//}
}

View File

@ -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();
}
}
}

View File

@ -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<Type> ILStack = new Stack<Type>();
//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);
}
}
}

View File

@ -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<Byte, Type> 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
}
}
}

View File

@ -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<long, LSO_Struct.StaticBlock> StaticBlocks = new Dictionary<long, LSO_Struct.StaticBlock>();
//private System.Collections.Hashtable StaticBlocks = new System.Collections.Hashtable();
private TypeBuilder typeBuilder;
private List<string> EventList = new List<string>();
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();
}
/// <summary>
/// Parse LSO file.
/// </summary>
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;
}
/// <summary>
/// Reads a code chunk and creates IL
/// </summary>
/// <param name="pos">Absolute position in file. REMEMBER TO ADD myHeader.GFR!</param>
/// <param name="typeBuilder">TypeBuilder for assembly</param>
/// <param name="eventname">Name of event (function) to generate</param>
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<LSO_Struct.CodeChunkArgument>();
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);
}
}
}
}

View File

@ -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<CodeChunkArgument> CodeChunkArguments;
public byte EndMarker;
public byte ReturnTypePos;
public StaticBlock ReturnType;
}
public struct CodeChunkArgument
{
public byte FunctionReturnTypePos;
public byte NullString;
public StaticBlock FunctionReturnType;
}
}
}

View File

@ -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
{
/// <summary>
/// Tedds Sandbox for RAIL/microtrheading. This class is only for testing purposes!
/// Its offspring will be the actual implementation.
/// </summary>
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;
}
}
}
/*
* 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
{
/// <summary>
/// This class encapsulated an LSO file and contains execution-specific data
/// </summary>
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)
{
}
}
}

View File

@ -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")]

View File

@ -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"; }
}
}
}

View File

@ -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 <int id, whatever script>
//internal Dictionary<uint, Dictionary<LLUUID, LSL_BaseClass>> Scripts = new Dictionary<uint, Dictionary<LLUUID, LSL_BaseClass>>();
// 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()
{
}
}
}

View File

@ -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);
}
}
}
/*
* 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);
}
}
}

View File

@ -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
{
/// <summary>
/// Handles events from OpenSim. Uses RemoteServer to send commands.
/// </summary>
[Serializable]
internal class EventManager
{
System.Collections.Generic.Dictionary<uint, ScriptServerInterfaces.ServerRemotingObject> remoteScript = new System.Collections.Generic.Dictionary<uint, ScriptServerInterfaces.ServerRemotingObject>();
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);
//}
}
}
/*
* 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
{
/// <summary>
/// Handles events from OpenSim. Uses RemoteServer to send commands.
/// </summary>
[Serializable]
internal class EventManager
{
System.Collections.Generic.Dictionary<uint, ScriptServerInterfaces.ServerRemotingObject> remoteScript = new System.Collections.Generic.Dictionary<uint, ScriptServerInterfaces.ServerRemotingObject>();
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);
//}
}
}

View File

@ -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")]
/*
* 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")]

View File

@ -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;
}
}
}

View File

@ -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
{
/// <summary>
/// This is the root object for RemoteServer. Objects access each other trough this class.
/// </summary>
///
[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
}
}
/*
* 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
{
/// <summary>
/// This is the root object for RemoteServer. Objects access each other trough this class.
/// </summary>
///
[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
}
}