* 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

@ -76,6 +76,10 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
}
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;
@ -133,7 +137,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
{
actor.Position.Y = 0.1F;
}
else if (actor.Position.Y >= 256)
else if (actor.Position.Y >= Constants.RegionSize)
{
actor.Position.Y = 255.9F;
}
@ -142,16 +146,16 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
{
actor.Position.X = 0.1F;
}
else if (actor.Position.X >= 256)
else if (actor.Position.X >= Constants.RegionSize)
{
actor.Position.X = 255.9F;
}
float height = _heightMap[(int) actor.Position.Y*256 + (int) actor.Position.X] + 1.0f;
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*256 + (int) actor.Position.X] + 2)
_heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 2)
{
actor.Position.Z = height;
actor.Velocity.Z = 0;
@ -224,6 +228,16 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
set { return; }
}
public override bool Grabbed
{
set { return; }
}
public override bool Selected
{
set { return; }
}
public override bool IsPhysical
{
get { return false; }
@ -260,6 +274,12 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
set { return; }
}
public override bool Stopped
{
get { return false; }
}
public override PhysicsVector Position
{
get { return _position; }
@ -303,6 +323,11 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
set { _velocity = value; }
}
public override float CollisionScore
{
get { return 0f; }
}
public override Quaternion Orientation
{
get { return Quaternion.Identity; }
@ -332,5 +357,9 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
public override void SetMomentum(PhysicsVector momentum)
{
}
public override void CrossingFailure()
{
}
}
}

View File

@ -13,7 +13,7 @@
* 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
* 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
@ -81,6 +81,8 @@ namespace OpenSim.Region.Physics.BulletXPlugin
/// </summary>
public class BulletXMaths
{
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//Vector3
public static Vector3 PhysicsVectorToXnaVector3(PhysicsVector physicsVector)
{
@ -311,9 +313,8 @@ namespace OpenSim.Region.Physics.BulletXPlugin
bool needsCollision = base.NeedsCollision(bodyA, bodyB);
MainLog.Instance.Debug("BulletX", "A collision was detected between {0} and {1} --> {2}", nameA, nameB,
needsCollision);
//m_log.DebugFormat("[BulletX]: A collision was detected between {0} and {1} --> {2}", nameA, nameB,
//needsCollision);
return needsCollision;
}
@ -334,7 +335,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
private const int minXY = 0;
private const int minZ = 0;
private const int maxXY = 256;
private const int maxXY = (int)Constants.RegionSize;
private const int maxZ = 4096;
private const int maxHandles = 32766; //Why? I don't know
private const float gravity = 9.8f;
@ -407,8 +408,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin
mesher = meshmerizer;
}
public override void Dispose()
{
public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID)
}
public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size)
{
PhysicsVector pos = new PhysicsVector();
pos.X = position.X;
@ -725,6 +729,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin
_name = name;
}
public override bool Stopped
{
get { return false; }
}
public override PhysicsVector Position
{
get { return _position; }
@ -764,7 +773,10 @@ namespace OpenSim.Region.Physics.BulletXPlugin
}
}
}
public override float CollisionScore
{
get { return 0f; }
}
public override PhysicsVector Size
{
get { return _size; }
@ -883,6 +895,16 @@ namespace OpenSim.Region.Physics.BulletXPlugin
set { return; }
}
public override bool Grabbed
{
set { return; }
}
public override bool Selected
{
set { return; }
}
public virtual void SetAcceleration(PhysicsVector accel)
{
lock (BulletXScene.BulletXLock)
@ -968,6 +990,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin
}
#endregion
public override void CrossingFailure()
{
}
}
/// <summary>
@ -976,7 +1003,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
public class BulletXCharacter : BulletXActor
{
public BulletXCharacter(BulletXScene parent_scene, PhysicsVector pos)
: this("", parent_scene, pos)
: this(String.Empty, parent_scene, pos)
{
}

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

@ -118,19 +118,30 @@ namespace OpenSim.Region.Physics.Manager
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)
{
OnRequestTerseUpdate();
handler();
}
}
@ -142,15 +153,19 @@ namespace OpenSim.Region.Physics.Manager
OutOfBounds handler = OnOutOfBounds;
if (handler != null)
{
OnOutOfBounds(pos);
handler(pos);
}
}
public virtual void SendCollisionUpdate(EventArgs e)
{
// CollisionUpdate handler = OnCollisionUpdate;
if (OnCollisionUpdate != null)
OnCollisionUpdate(e);
CollisionUpdate handler = OnCollisionUpdate;
if (handler != null)
{
handler(e);
}
}
@ -166,6 +181,8 @@ namespace OpenSim.Region.Physics.Manager
public abstract PhysicsVector Velocity { get; set; }
public abstract float CollisionScore { get;}
public abstract PhysicsVector Acceleration { get; }
public abstract Quaternion Orientation { get; set; }
@ -197,6 +214,11 @@ namespace OpenSim.Region.Physics.Manager
public class NullPhysicsActor : PhysicsActor
{
public override bool Stopped
{
get{ return false; }
}
public override PhysicsVector Position
{
get { return PhysicsVector.Zero; }
@ -209,6 +231,17 @@ namespace OpenSim.Region.Physics.Manager
set { return; }
}
public override bool Grabbed
{
set { return; }
}
public override bool Selected
{
set { return; }
}
public override bool CollidingGround
{
get { return false; }
@ -258,6 +291,17 @@ namespace OpenSim.Region.Physics.Manager
set { return; }
}
public override float CollisionScore
{
get { return 0f; }
}
public override void CrossingFailure()
{
}
public override Quaternion Orientation
{
get { return Quaternion.Identity; }

View File

@ -38,6 +38,8 @@ namespace OpenSim.Region.Physics.Manager
/// </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>();
@ -60,25 +62,25 @@ namespace OpenSim.Region.Physics.Manager
IMesher meshEngine = null;
if (_MeshPlugins.ContainsKey(meshEngineName))
{
MainLog.Instance.Verbose("PHYSICS", "creating meshing engine " + meshEngineName);
m_log.Info("[PHYSICS]: creating meshing engine " + meshEngineName);
meshEngine = _MeshPlugins[meshEngineName].GetMesher();
}
else
{
MainLog.Instance.Warn("PHYSICS", "couldn't find meshingEngine: {0}", meshEngineName);
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))
{
MainLog.Instance.Verbose("PHYSICS", "creating " + physEngineName);
m_log.Info("[PHYSICS]: creating " + physEngineName);
PhysicsScene result = _PhysPlugins[physEngineName].GetScene();
result.Initialise(meshEngine);
return result;
}
else
{
MainLog.Instance.Warn("PHYSICS", "couldn't find physicsEngine: {0}", physEngineName);
m_log.WarnFormat("[PHYSICS]: couldn't find physicsEngine: {0}", physEngineName);
throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", physEngineName));
}
}
@ -89,7 +91,7 @@ namespace OpenSim.Region.Physics.Manager
IMeshingPlugin plugHard;
plugHard = new ZeroMesherPlugin();
_MeshPlugins.Add(plugHard.GetName(), plugHard);
MainLog.Instance.Verbose("PHYSICS", "Added meshing engine: " + plugHard.GetName());
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
@ -104,8 +106,14 @@ namespace OpenSim.Region.Physics.Manager
private void AddPlugin(string FileName)
{
try
{
// 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())
@ -114,7 +122,12 @@ namespace OpenSim.Region.Physics.Manager
{
if (!pluginType.IsAbstract)
{
Type physTypeInterface = pluginType.GetInterface("IPhysicsPlugin", true);
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)
{
@ -125,18 +138,12 @@ namespace OpenSim.Region.Physics.Manager
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;
m_log.Info("[PHYSICS]: Added meshing engine: " + plug.GetName());
}
}
}
@ -154,11 +161,11 @@ namespace OpenSim.Region.Physics.Manager
{
if (isWarning)
{
MainLog.Instance.Warn("PHYSICS", message);
m_log.Warn("[PHYSICS]: " + message);
}
else
{
MainLog.Instance.Verbose("PHYSICS", message);
m_log.Info("[PHYSICS]: " + message);
}
}

View File

@ -25,6 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using System;
using Axiom.Math;
using OpenSim.Framework;
using OpenSim.Framework.Console;
@ -35,6 +36,8 @@ namespace OpenSim.Region.Physics.Manager
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.
@ -57,7 +60,7 @@ namespace OpenSim.Region.Physics.Manager
public abstract void Initialise(IMesher meshmerizer);
public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID); // rex, localID added
public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size);
public abstract void RemoveAvatar(PhysicsActor actor);
@ -78,6 +81,8 @@ namespace OpenSim.Region.Physics.Manager
public abstract void DeleteTerrain();
public abstract void Dispose();
public abstract bool IsThreaded { get; }
private class NullPhysicsScene : PhysicsScene
@ -90,9 +95,9 @@ namespace OpenSim.Region.Physics.Manager
// Does nothing right now
}
public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID)
public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size)
{
MainLog.Instance.Verbose("PHYSICS", "NullPhysicsScene : AddAvatar({0})", position);
m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddAvatar({0})", position);
return PhysicsActor.Null;
}
@ -107,7 +112,7 @@ namespace OpenSim.Region.Physics.Manager
/*
public override PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Quaternion rotation)
{
MainLog.Instance.Verbose("NullPhysicsScene : AddPrim({0},{1})", position, size);
m_log.InfoFormat("NullPhysicsScene : AddPrim({0},{1})", position, size);
return PhysicsActor.Null;
}
*/
@ -121,7 +126,7 @@ namespace OpenSim.Region.Physics.Manager
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);
m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : AddPrim({0},{1})", position, size);
return PhysicsActor.Null;
}
@ -133,18 +138,17 @@ namespace OpenSim.Region.Physics.Manager
{
m_workIndicator = (m_workIndicator + 1) % 10;
//MainLog.Instance.SetStatus(m_workIndicator.ToString());
return 0f;
}
public override void GetResults()
{
MainLog.Instance.Verbose("PHYSICS", "NullPhysicsScene : GetResults()");
m_log.Info("[PHYSICS]: NullPhysicsScene : GetResults()");
}
public override void SetTerrain(float[] heightMap)
{
MainLog.Instance.Verbose("PHYSICS", "NullPhysicsScene : SetTerrain({0} items)", heightMap.Length);
m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : SetTerrain({0} items)", heightMap.Length);
}
public override void DeleteTerrain()
@ -155,6 +159,10 @@ namespace OpenSim.Region.Physics.Manager
{
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

@ -46,7 +46,12 @@ namespace OpenSim.Region.Physics.Manager
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()
@ -54,6 +59,56 @@ namespace OpenSim.Region.Physics.Manager
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)
{

View File

@ -13,7 +13,7 @@
* 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
* 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

View File

@ -36,6 +36,13 @@ namespace OpenSim.Region.Physics.Meshing
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;
@ -49,10 +56,17 @@ namespace OpenSim.Region.Physics.Meshing
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;
v.Y *= size.Y;
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)
@ -60,9 +74,10 @@ namespace OpenSim.Region.Physics.Meshing
if (v == null)
continue;
// This is the bottom
v.Z = -.5f;
v.X *= size.X;
v.Y *= size.Y;
v.X *= (size.X * taperBotFactorX);
v.Y *= (size.Y * taperBotFactorY);
v.Z *= size.Z;
}

View File

@ -13,7 +13,7 @@
* 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
* 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

View File

@ -13,7 +13,7 @@
* 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
* 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
@ -53,10 +53,12 @@ namespace OpenSim.Region.Physics.Meshing
public class Meshmerizer : IMesher
{
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
// Setting baseDir to a path will enable the dumping of raw files
// raw files can be imported by blender so a visual inspection of the results can be done
// const string baseDir = "rawFiles";
private const string baseDir = null;
private const string baseDir = null; //"rawFiles";
private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2,
PhysicsVector r2, ref float lambda, ref float mu)
@ -101,7 +103,6 @@ namespace OpenSim.Region.Physics.Meshing
return influenced;
}
private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
{
// This is a variant of the delaunay algorithm
@ -174,6 +175,177 @@ namespace OpenSim.Region.Physics.Meshing
}
}
private static SimpleHull BuildHoleHull(PrimitiveBaseShape pbs, ProfileShape pshape, HollowShape hshape, UInt16 hollowFactor)
{
// Tackle HollowShape.Same
float fhollowFactor = (float)hollowFactor;
switch (pshape)
{
case ProfileShape.Square:
if (hshape == HollowShape.Same)
hshape= HollowShape.Square;
break;
case ProfileShape.EquilateralTriangle:
fhollowFactor = ((float)hollowFactor / 1.9f);
if (hshape == HollowShape.Same)
{
hshape = HollowShape.Triangle;
}
break;
case ProfileShape.Circle:
if (pbs.PathCurve == (byte)Extrusion.Straight)
{
if (hshape == HollowShape.Same)
{
hshape = HollowShape.Circle;
}
}
break;
default:
if (hshape == HollowShape.Same)
hshape= HollowShape.Square;
break;
}
SimpleHull holeHull = null;
if (hshape == HollowShape.Square)
{
float hollowFactorF = (float)fhollowFactor / (float)50000;
Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
holeHull = new SimpleHull();
holeHull.AddVertex(IMM);
holeHull.AddVertex(IMP);
holeHull.AddVertex(IPP);
holeHull.AddVertex(IPM);
}
if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
{
float hollowFactorF = (float)fhollowFactor / (float)50000;
Vertex IQ1Q15 = new Vertex(-0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
Vertex IQ1Q16 = new Vertex(-0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
Vertex IQ1Q17 = new Vertex(-0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
Vertex IQ1Q18 = new Vertex(-0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
Vertex IQ1Q19 = new Vertex(-0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
Vertex IQ2Q10 = new Vertex(+0.0f * hollowFactorF, -0.50f * hollowFactorF, 0.0f);
Vertex IQ2Q11 = new Vertex(+0.11f * hollowFactorF, -0.48f * hollowFactorF, 0.0f);
Vertex IQ2Q12 = new Vertex(+0.18f * hollowFactorF, -0.46f * hollowFactorF, 0.0f);
Vertex IQ2Q13 = new Vertex(+0.24f * hollowFactorF, -0.43f * hollowFactorF, 0.0f);
Vertex IQ2Q14 = new Vertex(+0.30f * hollowFactorF, -0.40f * hollowFactorF, 0.0f);
Vertex IQ2Q15 = new Vertex(+0.35f * hollowFactorF, -0.35f * hollowFactorF, 0.0f);
Vertex IQ2Q16 = new Vertex(+0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
Vertex IQ2Q17 = new Vertex(+0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
Vertex IQ2Q18 = new Vertex(+0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
Vertex IQ2Q19 = new Vertex(+0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
Vertex IQ2Q20 = new Vertex(+0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
Vertex IQ2Q21 = new Vertex(+0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
Vertex IQ2Q22 = new Vertex(+0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
Vertex IQ2Q23 = new Vertex(+0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
Vertex IQ2Q24 = new Vertex(+0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
Vertex IQ2Q25 = new Vertex(+0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
Vertex IQ2Q26 = new Vertex(+0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
Vertex IQ2Q27 = new Vertex(+0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
Vertex IQ2Q28 = new Vertex(+0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
Vertex IQ2Q29 = new Vertex(+0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
Vertex IQ1Q20 = new Vertex(+0.0f * hollowFactorF, +0.50f * hollowFactorF, 0.0f);
Vertex IQ1Q21 = new Vertex(-0.11f * hollowFactorF, +0.48f * hollowFactorF, 0.0f);
Vertex IQ1Q22 = new Vertex(-0.18f * hollowFactorF, +0.46f * hollowFactorF, 0.0f);
Vertex IQ1Q23 = new Vertex(-0.24f * hollowFactorF, +0.43f * hollowFactorF, 0.0f);
Vertex IQ1Q24 = new Vertex(-0.30f * hollowFactorF, +0.40f * hollowFactorF, 0.0f);
Vertex IQ1Q25 = new Vertex(-0.35f * hollowFactorF, +0.35f * hollowFactorF, 0.0f);
Vertex IQ1Q26 = new Vertex(-0.40f * hollowFactorF, +0.30f * hollowFactorF, 0.0f);
Vertex IQ1Q27 = new Vertex(-0.43f * hollowFactorF, +0.24f * hollowFactorF, 0.0f);
Vertex IQ1Q28 = new Vertex(-0.46f * hollowFactorF, +0.18f * hollowFactorF, 0.0f);
Vertex IQ1Q29 = new Vertex(-0.48f * hollowFactorF, +0.11f * hollowFactorF, 0.0f);
Vertex IQ1Q10 = new Vertex(-0.50f * hollowFactorF, +0.0f * hollowFactorF, 0.0f);
Vertex IQ1Q11 = new Vertex(-0.48f * hollowFactorF, -0.11f * hollowFactorF, 0.0f);
Vertex IQ1Q12 = new Vertex(-0.46f * hollowFactorF, -0.18f * hollowFactorF, 0.0f);
Vertex IQ1Q13 = new Vertex(-0.43f * hollowFactorF, -0.24f * hollowFactorF, 0.0f);
Vertex IQ1Q14 = new Vertex(-0.40f * hollowFactorF, -0.30f * hollowFactorF, 0.0f);
//Counter clockwise around the quadrants
holeHull = new SimpleHull();
holeHull.AddVertex(IQ1Q15);
holeHull.AddVertex(IQ1Q14);
holeHull.AddVertex(IQ1Q13);
holeHull.AddVertex(IQ1Q12);
holeHull.AddVertex(IQ1Q11);
holeHull.AddVertex(IQ1Q10);
holeHull.AddVertex(IQ1Q29);
holeHull.AddVertex(IQ1Q28);
holeHull.AddVertex(IQ1Q27);
holeHull.AddVertex(IQ1Q26);
holeHull.AddVertex(IQ1Q25);
holeHull.AddVertex(IQ1Q24);
holeHull.AddVertex(IQ1Q23);
holeHull.AddVertex(IQ1Q22);
holeHull.AddVertex(IQ1Q21);
holeHull.AddVertex(IQ1Q20);
holeHull.AddVertex(IQ2Q29);
holeHull.AddVertex(IQ2Q28);
holeHull.AddVertex(IQ2Q27);
holeHull.AddVertex(IQ2Q26);
holeHull.AddVertex(IQ2Q25);
holeHull.AddVertex(IQ2Q24);
holeHull.AddVertex(IQ2Q23);
holeHull.AddVertex(IQ2Q22);
holeHull.AddVertex(IQ2Q21);
holeHull.AddVertex(IQ2Q20);
holeHull.AddVertex(IQ2Q19);
holeHull.AddVertex(IQ2Q18);
holeHull.AddVertex(IQ2Q17);
holeHull.AddVertex(IQ2Q16);
holeHull.AddVertex(IQ2Q15);
holeHull.AddVertex(IQ2Q14);
holeHull.AddVertex(IQ2Q13);
holeHull.AddVertex(IQ2Q12);
holeHull.AddVertex(IQ2Q11);
holeHull.AddVertex(IQ2Q10);
holeHull.AddVertex(IQ1Q19);
holeHull.AddVertex(IQ1Q18);
holeHull.AddVertex(IQ1Q17);
holeHull.AddVertex(IQ1Q16);
}
if (hshape == HollowShape.Triangle)
{
float hollowFactorF = (float)fhollowFactor / (float)50000;
Vertex IMM = new Vertex(-0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f);
Vertex IPM = new Vertex(+0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f);
Vertex IPP = new Vertex(-0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f);
holeHull = new SimpleHull();
holeHull.AddVertex(IMM);
holeHull.AddVertex(IPP);
holeHull.AddVertex(IPM);
}
return holeHull;
}
private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the z (+ and -) surfaces of a box shaped prim
@ -181,6 +353,16 @@ namespace OpenSim.Region.Physics.Meshing
UInt16 hollowFactor = primShape.ProfileHollow;
UInt16 profileBegin = primShape.ProfileBegin;
UInt16 profileEnd = primShape.ProfileEnd;
UInt16 taperX = primShape.PathScaleX;
UInt16 taperY = primShape.PathScaleY;
UInt16 pathShearX = primShape.PathShearX;
UInt16 pathShearY = primShape.PathShearY;
//m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
//m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
//m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
//m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
// Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
// of a block are basically the same
@ -192,8 +374,8 @@ namespace OpenSim.Region.Physics.Meshing
// Base
Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
SimpleHull outerHull = new SimpleHull();
outerHull.AddVertex(MM);
@ -236,7 +418,7 @@ namespace OpenSim.Region.Physics.Meshing
// Calculated separately to avoid errors
cutHull.AddVertex(legEnd);
MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName);
//m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
outerHull = cuttedHull;
@ -245,23 +427,15 @@ namespace OpenSim.Region.Physics.Meshing
// Deal with the hole here
if (hollowFactor > 0)
{
float hollowFactorF = (float) hollowFactor/(float) 50000;
Vertex IMM = new Vertex(-0.5f*hollowFactorF, -0.5f*hollowFactorF, 0.0f);
Vertex IPM = new Vertex(+0.5f*hollowFactorF, -0.5f*hollowFactorF, 0.0f);
Vertex IMP = new Vertex(-0.5f*hollowFactorF, +0.5f*hollowFactorF, 0.0f);
Vertex IPP = new Vertex(+0.5f*hollowFactorF, +0.5f*hollowFactorF, 0.0f);
SimpleHull holeHull = new SimpleHull();
holeHull.AddVertex(IMM);
holeHull.AddVertex(IMP);
holeHull.AddVertex(IPP);
holeHull.AddVertex(IPM);
SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
if (holeHull != null)
{
SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
outerHull = hollowedHull;
}
}
Mesh m = new Mesh();
@ -298,6 +472,512 @@ namespace OpenSim.Region.Physics.Meshing
extr.size = size;
if (taperX != 100)
{
if (taperX > 100)
{
extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
//m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
}
else
{
extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
//m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
}
}
if (taperY != 100)
{
if (taperY > 100)
{
extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
//m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
}
else
{
extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
//m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
}
}
if (pathShearX != 0)
{
if (pathShearX > 50) {
// Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
// m_log.Warn("pushX: " + extr.pushX);
}
else
{
extr.pushX = (float)pathShearX / 100;
// m_log.Warn("pushX: " + extr.pushX);
}
}
if (pathShearY != 0)
{
if (pathShearY > 50) {
// Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
//m_log.Warn("pushY: " + extr.pushY);
}
else
{
extr.pushY = (float)pathShearY / 100;
//m_log.Warn("pushY: " + extr.pushY);
}
}
Mesh result = extr.Extrude(m);
result.DumpRaw(baseDir, primName, "Z extruded");
return result;
}
private static Mesh CreateCyllinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the z (+ and -) surfaces of a box shaped prim
{
UInt16 hollowFactor = primShape.ProfileHollow;
UInt16 profileBegin = primShape.ProfileBegin;
UInt16 profileEnd = primShape.ProfileEnd;
UInt16 taperX = primShape.PathScaleX;
UInt16 taperY = primShape.PathScaleY;
UInt16 pathShearX = primShape.PathShearX;
UInt16 pathShearY = primShape.PathShearY;
// Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
// of a block are basically the same
// They may be warped differently but the shape is identical
// So we only create one surface as a model and derive both plus and minus surface of the block from it
// This is done in a model space where the block spans from -.5 to +.5 in X and Y
// The mapping to Scene space is done later during the "extrusion" phase
// Base
// Q1Q15 = Quadrant 1, Quadrant1, Vertex 5
Vertex Q1Q15 = new Vertex(-0.35f, -0.35f, 0.0f);
Vertex Q1Q16 = new Vertex(-0.30f, -0.40f, 0.0f);
Vertex Q1Q17 = new Vertex(-0.24f, -0.43f, 0.0f);
Vertex Q1Q18 = new Vertex(-0.18f, -0.46f, 0.0f);
Vertex Q1Q19 = new Vertex(-0.11f, -0.48f, 0.0f);
Vertex Q2Q10 = new Vertex(+0.0f, -0.50f, 0.0f);
Vertex Q2Q11 = new Vertex(+0.11f, -0.48f, 0.0f);
Vertex Q2Q12 = new Vertex(+0.18f, -0.46f, 0.0f);
Vertex Q2Q13 = new Vertex(+0.24f, -0.43f, 0.0f);
Vertex Q2Q14 = new Vertex(+0.30f, -0.40f, 0.0f);
Vertex Q2Q15 = new Vertex(+0.35f, -0.35f, 0.0f);
Vertex Q2Q16 = new Vertex(+0.40f, -0.30f, 0.0f);
Vertex Q2Q17 = new Vertex(+0.43f, -0.24f, 0.0f);
Vertex Q2Q18 = new Vertex(+0.46f, -0.18f, 0.0f);
Vertex Q2Q19 = new Vertex(+0.48f, -0.11f, 0.0f);
Vertex Q2Q20 = new Vertex(+0.50f, +0.0f, 0.0f);
Vertex Q2Q21 = new Vertex(+0.48f, +0.11f, 0.0f);
Vertex Q2Q22 = new Vertex(+0.46f, +0.18f, 0.0f);
Vertex Q2Q23 = new Vertex(+0.43f, +0.24f, 0.0f);
Vertex Q2Q24 = new Vertex(+0.40f, +0.30f, 0.0f);
Vertex Q2Q25 = new Vertex(+0.35f, +0.35f, 0.0f);
Vertex Q2Q26 = new Vertex(+0.30f, +0.40f, 0.0f);
Vertex Q2Q27 = new Vertex(+0.24f, +0.43f, 0.0f);
Vertex Q2Q28 = new Vertex(+0.18f, +0.46f, 0.0f);
Vertex Q2Q29 = new Vertex(+0.11f, +0.48f, 0.0f);
Vertex Q1Q20 = new Vertex(+0.0f, +0.50f, 0.0f);
Vertex Q1Q21 = new Vertex(-0.11f, +0.48f, 0.0f);
Vertex Q1Q22 = new Vertex(-0.18f, +0.46f, 0.0f);
Vertex Q1Q23 = new Vertex(-0.24f, +0.43f, 0.0f);
Vertex Q1Q24 = new Vertex(-0.30f, +0.40f, 0.0f);
Vertex Q1Q25 = new Vertex(-0.35f, +0.35f, 0.0f);
Vertex Q1Q26 = new Vertex(-0.40f, +0.30f, 0.0f);
Vertex Q1Q27 = new Vertex(-0.43f, +0.24f, 0.0f);
Vertex Q1Q28 = new Vertex(-0.46f, +0.18f, 0.0f);
Vertex Q1Q29 = new Vertex(-0.48f, +0.11f, 0.0f);
Vertex Q1Q10 = new Vertex(-0.50f, +0.0f, 0.0f);
Vertex Q1Q11 = new Vertex(-0.48f, -0.11f, 0.0f);
Vertex Q1Q12 = new Vertex(-0.46f, -0.18f, 0.0f);
Vertex Q1Q13 = new Vertex(-0.43f, -0.24f, 0.0f);
Vertex Q1Q14 = new Vertex(-0.40f, -0.30f, 0.0f);
SimpleHull outerHull = new SimpleHull();
//Clockwise around the quadrants
outerHull.AddVertex(Q1Q15);
outerHull.AddVertex(Q1Q16);
outerHull.AddVertex(Q1Q17);
outerHull.AddVertex(Q1Q18);
outerHull.AddVertex(Q1Q19);
outerHull.AddVertex(Q2Q10);
outerHull.AddVertex(Q2Q11);
outerHull.AddVertex(Q2Q12);
outerHull.AddVertex(Q2Q13);
outerHull.AddVertex(Q2Q14);
outerHull.AddVertex(Q2Q15);
outerHull.AddVertex(Q2Q16);
outerHull.AddVertex(Q2Q17);
outerHull.AddVertex(Q2Q18);
outerHull.AddVertex(Q2Q19);
outerHull.AddVertex(Q2Q20);
outerHull.AddVertex(Q2Q21);
outerHull.AddVertex(Q2Q22);
outerHull.AddVertex(Q2Q23);
outerHull.AddVertex(Q2Q24);
outerHull.AddVertex(Q2Q25);
outerHull.AddVertex(Q2Q26);
outerHull.AddVertex(Q2Q27);
outerHull.AddVertex(Q2Q28);
outerHull.AddVertex(Q2Q29);
outerHull.AddVertex(Q1Q20);
outerHull.AddVertex(Q1Q21);
outerHull.AddVertex(Q1Q22);
outerHull.AddVertex(Q1Q23);
outerHull.AddVertex(Q1Q24);
outerHull.AddVertex(Q1Q25);
outerHull.AddVertex(Q1Q26);
outerHull.AddVertex(Q1Q27);
outerHull.AddVertex(Q1Q28);
outerHull.AddVertex(Q1Q29);
outerHull.AddVertex(Q1Q10);
outerHull.AddVertex(Q1Q11);
outerHull.AddVertex(Q1Q12);
outerHull.AddVertex(Q1Q13);
outerHull.AddVertex(Q1Q14);
// Deal with cuts now
if ((profileBegin != 0) || (profileEnd != 0))
{
double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
// In degree, for easier debugging and understanding
//fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
//fProfileEndAngle -= (90.0 + 45.0);
if (fProfileBeginAngle < fProfileEndAngle)
fProfileEndAngle -= 360.0;
// Note, that we don't want to cut out a triangle, even if this is a
// good approximation for small cuts. Indeed we want to cut out an arc
// and we approximate this arc by a polygon chain
// Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
// So it can easily be subtracted from the outer hull
int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
// how many steps do we need with approximately 45 degree
double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
// Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
SimpleHull cutHull = new SimpleHull();
cutHull.AddVertex(origin);
for (int i = 0; i < iSteps; i++)
{
double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
cutHull.AddVertex(v);
}
Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
// Calculated separately to avoid errors
cutHull.AddVertex(legEnd);
// m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
outerHull = cuttedHull;
}
// Deal with the hole here
if (hollowFactor > 0)
{
SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
if (holeHull != null)
{
SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
outerHull = hollowedHull;
}
}
Mesh m = new Mesh();
Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
m.Add(Seed1);
m.Add(Seed2);
m.Add(Seed3);
m.Add(new Triangle(Seed1, Seed2, Seed3));
m.Add(outerHull.getVertices());
InsertVertices(m.vertices, 3, m.triangles);
m.DumpRaw(baseDir, primName, "Proto first Mesh");
m.Remove(Seed1);
m.Remove(Seed2);
m.Remove(Seed3);
m.DumpRaw(baseDir, primName, "Proto seeds removed");
m.RemoveTrianglesOutside(outerHull);
m.DumpRaw(baseDir, primName, "Proto outsides removed");
foreach (Triangle t in m.triangles)
{
PhysicsVector n = t.getNormal();
if (n.Z < 0.0)
t.invertNormal();
}
Extruder extr = new Extruder();
extr.size = size;
if (taperX != 100)
{
if (taperX > 100)
{
extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
//m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
}
else
{
extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
//m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
}
}
if (taperY != 100)
{
if (taperY > 100)
{
extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
//m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
}
else
{
extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
//m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
}
}
if (pathShearX != 0)
{
if (pathShearX > 50)
{
// Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
//m_log.Warn("pushX: " + extr.pushX);
}
else
{
extr.pushX = (float)pathShearX / 100;
//m_log.Warn("pushX: " + extr.pushX);
}
}
if (pathShearY != 0)
{
if (pathShearY > 50)
{
// Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
//m_log.Warn("pushY: " + extr.pushY);
}
else
{
extr.pushY = (float)pathShearY / 100;
//m_log.Warn("pushY: " + extr.pushY);
}
}
Mesh result = extr.Extrude(m);
result.DumpRaw(baseDir, primName, "Z extruded");
return result;
}
private static Mesh CreatePrismMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
// Builds the z (+ and -) surfaces of a box shaped prim
{
UInt16 hollowFactor = primShape.ProfileHollow;
UInt16 profileBegin = primShape.ProfileBegin;
UInt16 profileEnd = primShape.ProfileEnd;
UInt16 taperX = primShape.PathScaleX;
UInt16 taperY = primShape.PathScaleY;
UInt16 pathShearX = primShape.PathShearX;
UInt16 pathShearY = primShape.PathShearY;
//m_log.Error("pathShear:" + primShape.PathShearX.ToString() + "," + primShape.PathShearY.ToString());
//m_log.Error("pathTaper:" + primShape.PathTaperX.ToString() + "," + primShape.PathTaperY.ToString());
//m_log.Error("ProfileBegin:" + primShape.ProfileBegin.ToString() + "," + primShape.ProfileBegin.ToString());
//m_log.Error("PathScale:" + primShape.PathScaleX.ToString() + "," + primShape.PathScaleY.ToString());
// Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
// of a block are basically the same
// They may be warped differently but the shape is identical
// So we only create one surface as a model and derive both plus and minus surface of the block from it
// This is done in a model space where the block spans from -.5 to +.5 in X and Y
// The mapping to Scene space is done later during the "extrusion" phase
// Base
Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
SimpleHull outerHull = new SimpleHull();
outerHull.AddVertex(MM);
outerHull.AddVertex(PM);
outerHull.AddVertex(PP);
// Deal with cuts now
if ((profileBegin != 0) || (profileEnd != 0))
{
double fProfileBeginAngle = profileBegin / 50000.0 * 360.0;
// In degree, for easier debugging and understanding
//fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
//fProfileEndAngle -= (90.0 + 45.0);
if (fProfileBeginAngle < fProfileEndAngle)
fProfileEndAngle -= 360.0;
// Note, that we don't want to cut out a triangle, even if this is a
// good approximation for small cuts. Indeed we want to cut out an arc
// and we approximate this arc by a polygon chain
// Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
// So it can easily be subtracted from the outer hull
int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5);
// how many steps do we need with approximately 45 degree
double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps;
Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
// Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
SimpleHull cutHull = new SimpleHull();
cutHull.AddVertex(origin);
for (int i = 0; i < iSteps; i++)
{
double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!!
Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
cutHull.AddVertex(v);
}
Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0);
// Calculated separately to avoid errors
cutHull.AddVertex(legEnd);
//m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName);
SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
outerHull = cuttedHull;
}
// Deal with the hole here
if (hollowFactor > 0)
{
SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor);
if (holeHull != null)
{
SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
outerHull = hollowedHull;
}
}
Mesh m = new Mesh();
Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
m.Add(Seed1);
m.Add(Seed2);
m.Add(Seed3);
m.Add(new Triangle(Seed1, Seed2, Seed3));
m.Add(outerHull.getVertices());
InsertVertices(m.vertices, 3, m.triangles);
m.DumpRaw(baseDir, primName, "Proto first Mesh");
m.Remove(Seed1);
m.Remove(Seed2);
m.Remove(Seed3);
m.DumpRaw(baseDir, primName, "Proto seeds removed");
m.RemoveTrianglesOutside(outerHull);
m.DumpRaw(baseDir, primName, "Proto outsides removed");
foreach (Triangle t in m.triangles)
{
PhysicsVector n = t.getNormal();
if (n.Z < 0.0)
t.invertNormal();
}
Extruder extr = new Extruder();
extr.size = size;
if (taperX != 100)
{
if (taperX > 100)
{
extr.taperTopFactorX = 1.0f - ((float)taperX / 200);
//m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
}
else
{
extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100);
//m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
}
}
if (taperY != 100)
{
if (taperY > 100)
{
extr.taperTopFactorY = 1.0f - ((float)taperY / 200);
//m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
}
else
{
extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100);
//m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
}
}
if (pathShearX != 0)
{
if (pathShearX > 50)
{
// Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
extr.pushX = (((float)(256 - pathShearX) / 100) * -1f);
// m_log.Warn("pushX: " + extr.pushX);
}
else
{
extr.pushX = (float)pathShearX / 100;
// m_log.Warn("pushX: " + extr.pushX);
}
}
if (pathShearY != 0)
{
if (pathShearY > 50)
{
// Complimentary byte. Negative values wrap around the byte. Positive values go up to 50
extr.pushY = (((float)(256 - pathShearY) / 100) * -1f);
//m_log.Warn("pushY: " + extr.pushY);
}
else
{
extr.pushY = (float)pathShearY / 100;
//m_log.Warn("pushY: " + extr.pushY);
}
}
Mesh result = extr.Extrude(m);
result.DumpRaw(baseDir, primName, "Z extruded");
return result;
@ -374,6 +1054,18 @@ namespace OpenSim.Region.Physics.Meshing
mesh = CreateBoxMesh(primName, primShape, size);
CalcNormals(mesh);
break;
case ProfileShape.Circle:
if (primShape.PathCurve == (byte)Extrusion.Straight)
{
mesh = CreateCyllinderMesh(primName, primShape, size);
CalcNormals(mesh);
}
break;
case ProfileShape.EquilateralTriangle:
mesh = CreatePrismMesh(primName, primShape, size);
CalcNormals(mesh);
break;
default:
mesh = CreateBoxMesh(primName, primShape, size);
CalcNormals(mesh);

View File

@ -42,6 +42,8 @@ namespace OpenSim.Region.Physics.Meshing
// 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
@ -53,7 +55,7 @@ namespace OpenSim.Region.Physics.Meshing
public override String ToString()
{
String result = "";
String result = String.Empty;
foreach (Vertex v in vertices)
{
result += "b:" + v.ToString() + "\n";
@ -226,8 +228,8 @@ namespace OpenSim.Region.Physics.Meshing
distToV1 = distTemp;
bestIntersectingSimplex = sTest;
}
} // end if vTemp
} // end foreach
}
}
Intersection = bestIntersection;
if (bestIntersectingSimplex != null)
@ -243,9 +245,9 @@ namespace OpenSim.Region.Physics.Meshing
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());
//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;
@ -274,8 +276,8 @@ namespace OpenSim.Region.Physics.Meshing
}
}
MainLog.Instance.Debug("State after intersection detection for the base hull");
MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString());
//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;
@ -303,9 +305,8 @@ namespace OpenSim.Region.Physics.Meshing
}
}
MainLog.Instance.Debug("State after intersection detection for the base hull");
MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString());
//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)
@ -315,7 +316,6 @@ namespace OpenSim.Region.Physics.Meshing
return baseHullClone;
}
SimpleHull result = new SimpleHull();
// Find a good starting Simplex from baseHull
@ -387,7 +387,7 @@ namespace OpenSim.Region.Physics.Meshing
done = true;
}
MainLog.Instance.Debug("The resulting Hull is:\n{1}", 0, result.ToString());
//m_log.DebugFormat("The resulting Hull is:\n{1}", 0, result.ToString());
return result;
}

View File

@ -35,8 +35,30 @@ using System.Runtime.InteropServices; // rex
namespace OpenSim.Region.Physics.OdePlugin
{
/// <summary>
/// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
/// </summary>
public enum dParam : int
{
LowStop = 0,
HiStop = 1,
Vel = 2,
FMax = 3,
FudgeFactor = 4,
Bounce = 5,
CFM = 6,
ERP = 7,
StopCFM = 8,
LoStop2 = 256,
HiStop2 = 257,
LoStop3 = 512,
HiStop3 = 513
}
public class OdeCharacter : PhysicsActor
{
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private PhysicsVector _position;
private d.Vector3 _zeroPosition;
private d.Matrix3 m_StandUpRotation;
@ -46,13 +68,15 @@ namespace OpenSim.Region.Physics.OdePlugin
private PhysicsVector _target_velocity;
private PhysicsVector _acceleration;
private PhysicsVector m_rotationalVelocity;
private float m_density = 50f;
private float m_mass = 80f;
private float m_density = 60f;
private bool m_pidControllerActive = true;
private static float PID_D = 3020.0f;
private static float PID_P = 7000.0f;
private float PID_D = 800.0f;
private float PID_P = 900.0f;
private static float POSTURE_SERVO = 10000.0f;
public static float CAPSULE_RADIUS = 0.5f;
public float CAPSULE_LENGTH = 0.79f;
public static float CAPSULE_RADIUS = 0.37f;
public float CAPSULE_LENGTH = 2.140599f;
private float m_tensor = 3800000f;
private bool flying = false;
private bool m_iscolliding = false;
private bool m_iscollidingGround = false;
@ -63,7 +87,10 @@ namespace OpenSim.Region.Physics.OdePlugin
private bool m_alwaysRun = false;
private bool m_hackSentFall = false;
private bool m_hackSentFly = false;
private string m_name = "";
private bool m_foundDebian = false;
private CollisionLocker ode;
private string m_name = String.Empty;
private bool[] m_colliderarr = new bool[11];
private bool[] m_colliderGroundarr = new bool[11];
@ -82,26 +109,38 @@ namespace OpenSim.Region.Physics.OdePlugin
public d.Mass ShellMass;
public bool collidelock = false;
public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, uint localID) // rex, localID added
public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, CollisionLocker dode, PhysicsVector size)
{
m_localID = localID; // rex
ode = dode;
_velocity = new PhysicsVector();
_target_velocity = new PhysicsVector();
_position = pos;
_acceleration = new PhysicsVector();
_parent_scene = parent_scene;
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
{
m_foundDebian = true;
m_tensor = 2000000f;
}
else
{
m_tensor = 1300000f;
}
m_StandUpRotation =
new d.Matrix3(0.8184158f, -0.5744568f, -0.0139677f, 0.5744615f, 0.8185215f, -0.004074608f, 0.01377355f,
-0.004689182f, 0.9998941f);
new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f,
0.5f);
for (int i = 0; i < 11; i++)
{
m_colliderarr[i] = false;
}
CAPSULE_LENGTH = (size.Z - ((size.Z * 0.52f)));
lock (OdeScene.OdeLock)
{
AvatarGeomAndBodyCreation(pos.X, pos.Y, pos.Z, m_tensor);
int dAMotorEuler = 1;
Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
gchShell = GCHandle.Alloc(Shell, GCHandleType.Pinned); // rex
@ -146,12 +185,26 @@ namespace OpenSim.Region.Physics.OdePlugin
set { return; }
}
/// <summary>
/// If this is set, the avatar will move faster
/// </summary>
public override bool SetAlwaysRun
{
get { return m_alwaysRun; }
set { m_alwaysRun = value; }
}
public override bool Grabbed
{
set { return; }
}
public override bool Selected
{
set { return; }
}
public override bool IsPhysical
{
get { return false; }
@ -170,6 +223,10 @@ namespace OpenSim.Region.Physics.OdePlugin
set { flying = value; }
}
/// <summary>
/// Returns if the avatar is colliding in general.
/// This includes the ground and objects and avatar.
/// </summary>
public override bool IsColliding
{
get { return m_iscolliding; }
@ -218,11 +275,17 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
/// <summary>
/// Returns if an avatar is colliding with the ground
/// </summary>
public override bool CollidingGround
{
get { return m_iscollidingGround; }
set
{
// Collisions against the ground are not really reliable
// So, to get a consistant value we have to average the current result over time
// Currently we use 1 second = 10 calls to this.
int i;
int truecount = 0;
int falsecount = 0;
@ -266,6 +329,9 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
/// <summary>
/// Returns if the avatar is colliding with an object
/// </summary>
public override bool CollidingObj
{
get { return m_iscollidingObj; }
@ -279,11 +345,26 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
/// <summary>
/// turn the PID controller on or off.
/// The PID Controller will turn on all by itself in many situations
/// </summary>
/// <param name="status"></param>
public void SetPidStatus(bool status)
{
m_pidControllerActive = status;
}
public override bool Stopped
{
get { return _zeroFlag; }
}
/// <summary>
/// This 'puts' an avatar somewhere in the physics space.
/// Not really a good choice unless you 'know' it's a good
/// spot otherwise you're likely to orbit the avatar.
/// </summary>
public override PhysicsVector Position
{
get { return _position; }
@ -303,6 +384,10 @@ namespace OpenSim.Region.Physics.OdePlugin
set { m_rotationalVelocity = value; }
}
/// <summary>
/// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
/// and use it to offset landings properly
/// </summary>
public override PhysicsVector Size
{
get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); }
@ -311,15 +396,24 @@ namespace OpenSim.Region.Physics.OdePlugin
m_pidControllerActive = true;
lock (OdeScene.OdeLock)
{
d.JointDestroy(Amotor);
PhysicsVector SetSize = value;
float prevCapsule = CAPSULE_LENGTH;
float capsuleradius = CAPSULE_RADIUS;
capsuleradius = 0.2f;
//capsuleradius = 0.2f;
CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.43f))); // subtract 43% of the size
CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.52f))); // subtract 43% of the size
//m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
d.BodyDestroy(Body);
gchBody.Free(); // rex
_parent_scene.waitForSpaceUnlock(_parent_scene.space);
d.GeomDestroy(Shell);
AvatarGeomAndBodyCreation(_position.X, _position.Y,
_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
Velocity = new PhysicsVector(0f, 0f, 0f);
gchShell.Free(); // rex
//MainLog.Instance.Verbose("PHYSICS", "Set Avatar Height To: " + (CAPSULE_RADIUS + CAPSULE_LENGTH));
Shell = d.CreateCapsule(_parent_scene.space, capsuleradius, CAPSULE_LENGTH);
@ -336,7 +430,86 @@ namespace OpenSim.Region.Physics.OdePlugin
_parent_scene.actor_name_map[Shell] = (PhysicsActor) this;
}
}
/// <summary>
/// This creates the Avatar's physical Surrogate at the position supplied
/// </summary>
/// <param name="npositionX"></param>
/// <param name="npositionY"></param>
/// <param name="npositionZ"></param>
private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor)
{
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
{
m_foundDebian = true;
m_tensor = 2000000f;
}
else
{
m_tensor = 550000f;
}
int dAMotorEuler = 1;
_parent_scene.waitForSpaceUnlock(_parent_scene.space);
Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
Body = d.BodyCreate(_parent_scene.world);
d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
d.BodySetMass(Body, ref ShellMass);
d.Matrix3 m_caprot;
// 90 Stand up on the cap of the capped cyllinder
d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
d.GeomSetRotation(Shell, ref m_caprot);
d.BodySetRotation(Body, ref m_caprot);
d.GeomSetBody(Shell, Body);
// The purpose of the AMotor here is to keep the avatar's physical
// surrogate from rotating while moving
Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
d.JointAttach(Amotor, Body, IntPtr.Zero);
d.JointSetAMotorMode(Amotor, dAMotorEuler);
d.JointSetAMotorNumAxes(Amotor, 3);
d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
d.JointSetAMotorAngle(Amotor, 0, 0);
d.JointSetAMotorAngle(Amotor, 1, 0);
d.JointSetAMotorAngle(Amotor, 2, 0);
// These lowstops and high stops are effectively (no wiggle room)
d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
// Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
// capped cyllinder will fall over
d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
//d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
//d.QfromR(
//d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
//
//m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
//standupStraight();
}
//
/// <summary>
/// Uses the capped cyllinder volume formula to calculate the avatar's mass.
/// This may be used in calculations in the scene/scenepresence
/// </summary>
public override float Mass
{
get
@ -346,6 +519,27 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
private void standupStraight()
{
// The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air.
// The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you
// change appearance and when you enter the simulator
// After this routine is done, the amotor stabilizes much quicker
d.Vector3 feet;
d.Vector3 head;
d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
float posture = head.Z - feet.Z;
// restoring force proportional to lack of posture:
float servo = (2.5f - posture) * POSTURE_SERVO;
d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
//d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
//m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
}
public override PhysicsVector Force
{
get { return new PhysicsVector(_target_velocity.X, _target_velocity.Y, _target_velocity.Z); }
@ -368,7 +562,13 @@ namespace OpenSim.Region.Physics.OdePlugin
public override PhysicsVector Velocity
{
get { return _velocity; }
get {
// There's a problem with PhysicsVector.Zero! Don't Use it Here!
if (_zeroFlag)
return new PhysicsVector(0f, 0f, 0f);
m_lastUpdateSent = false;
return _velocity;
}
set
{
m_pidControllerActive = true;
@ -376,6 +576,11 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
public override float CollisionScore
{
get { return 0f; }
}
public override bool Kinematic
{
get { return false; }
@ -385,7 +590,12 @@ namespace OpenSim.Region.Physics.OdePlugin
public override Quaternion Orientation
{
get { return Quaternion.Identity; }
set { }
set {
//Matrix3 or = Orientation.ToRotationMatrix();
//d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22);
//d.BodySetRotation(Body, ref ord);
}
}
public override PhysicsVector Acceleration
@ -399,6 +609,11 @@ namespace OpenSim.Region.Physics.OdePlugin
_acceleration = accel;
}
/// <summary>
/// Adds the force supplied to the Target Velocity
/// The PID controller takes this target velocity and tries to make it a reality
/// </summary>
/// <param name="force"></param>
public override void AddForce(PhysicsVector force)
{
m_pidControllerActive = true;
@ -409,29 +624,18 @@ namespace OpenSim.Region.Physics.OdePlugin
//m_lastUpdateSent = false;
}
/// <summary>
/// After all of the forces add up with 'add force' we apply them with doForce
/// </summary>
/// <param name="force"></param>
public void doForce(PhysicsVector force)
{
if (!collidelock)
{
d.BodyAddForce(Body, force.X, force.Y, force.Z);
// ok -- let's stand up straight!
//d.Matrix3 StandUpRotationalMatrix = new d.Matrix3(0.8184158f, -0.5744568f, -0.0139677f, 0.5744615f, 0.8185215f, -0.004074608f, 0.01377355f, -0.004689182f, 0.9998941f);
//d.BodySetRotation(Body, ref StandUpRotationalMatrix);
//d.BodySetRotation(Body, ref m_StandUpRotation);
// The above matrix was generated with the amazing standup routine below by danX0r *cheer*
d.Vector3 feet;
d.Vector3 head;
d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
float posture = head.Z - feet.Z;
//standupStraight();
// restoring force proportional to lack of posture:
float servo = (2.5f - posture) * POSTURE_SERVO;
d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
//m_lastUpdateSent = false;
}
}
@ -439,9 +643,30 @@ namespace OpenSim.Region.Physics.OdePlugin
{
}
/// <summary>
/// Called from Simulate
/// This is the avatar's movement control + PID Controller
/// </summary>
/// <param name="timeStep"></param>
public void Move(float timeStep)
{
// no lock; for now it's only called from within Simulate()
// If the PID Controller isn't active then we set our force
// calculating base velocity to the current position
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
{
PID_D = 3200.0f;
PID_P = 1400.0f;
}
else
{
PID_D = 2200.0f;
PID_P = 900.0f;
}
if (m_pidControllerActive == false)
{
_zeroPosition = d.BodyGetPosition(Body);
@ -472,12 +697,17 @@ namespace OpenSim.Region.Physics.OdePlugin
}
if (m_pidControllerActive)
{
// We only want to deactivate the PID Controller if we think we want to have our surrogate
// react to the physics scene by moving it's position.
// Avatar to Avatar collisions
// Prim to avatar collisions
d.Vector3 pos = d.BodyGetPosition(Body);
vec.X = (_target_velocity.X - vel.X)*PID_D + (_zeroPosition.X - pos.X)*PID_P;
vec.Y = (_target_velocity.Y - vel.Y)*PID_D + (_zeroPosition.Y - pos.Y)*PID_P;
vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
vec.Y = (_target_velocity.Y - vel.Y)*(PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2);
if (flying)
{
vec.Z = (_target_velocity.Z - vel.Z)*(PID_D + 5100) + (_zeroPosition.Z - pos.Z)*PID_P;
vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
}
}
//PidStatus = true;
@ -486,13 +716,29 @@ namespace OpenSim.Region.Physics.OdePlugin
{
m_pidControllerActive = true;
_zeroFlag = false;
if (m_iscolliding || flying)
if (m_iscolliding && !flying)
{
vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*PID_D;
vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*PID_D;
// We're flying and colliding with something
vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
}
else if (m_iscolliding && flying)
{
// We're flying and colliding with something
vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16);
vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16);
}
else if (!m_iscolliding && flying)
{
// We're flying and colliding with something
vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6);
vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6);
}
if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
{
// We're colliding with something and we're not flying but we're moving
// This means we're walking or running.
d.Vector3 pos = d.BodyGetPosition(Body);
vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
if (_target_velocity.X > 0)
@ -506,6 +752,8 @@ namespace OpenSim.Region.Physics.OdePlugin
}
else if (!m_iscolliding && !flying)
{
// we're not colliding and we're not flying so that means we're falling!
// m_iscolliding includes collisions with the ground.
d.Vector3 pos = d.BodyGetPosition(Body);
if (_target_velocity.X > 0)
{
@ -520,18 +768,21 @@ namespace OpenSim.Region.Physics.OdePlugin
if (flying)
{
vec.Z = (_target_velocity.Z - vel.Z)*(PID_D + 5100);
vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
}
}
if (flying)
{
vec.Z += 10.0f;
vec.Z += (9.8f*m_mass);
}
doForce(vec);
}
/// <summary>
/// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
/// </summary>
public void UpdatePositionAndVelocity()
{
// no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
@ -547,25 +798,21 @@ namespace OpenSim.Region.Physics.OdePlugin
_position.Y = vec.Y;
_position.Z = vec.Z;
// Did we move last? = zeroflag
// This helps keep us from sliding all over
if (_zeroFlag)
{
_velocity.X = 0.0f;
_velocity.Y = 0.0f;
_velocity.Z = 0.0f;
// Did we send out the 'stopped' message?
if (!m_lastUpdateSent)
{
m_lastUpdateSent = true;
base.RequestPhysicsterseUpdate();
//string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
//int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
//if (primScenAvatarIn == "0")
//{
//MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in space with no prim. Arr:':" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
//}
//else
//{
// MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in Prim space':" + primScenAvatarIn + ". Arr:" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
//}
//base.RequestPhysicsterseUpdate();
}
}
else
@ -578,6 +825,7 @@ namespace OpenSim.Region.Physics.OdePlugin
_velocity.Z = (vec.Z);
if (_velocity.Z < -6 && !m_hackSentFall)
{
// Collisionupdates will be used in the future, right now the're not being used.
m_hackSentFall = true;
//base.SendCollisionUpdate(new CollisionEventUpdate());
m_pidControllerActive = false;
@ -595,15 +843,29 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
/// <summary>
/// Cleanup the things we use in the scene.
/// </summary>
public void Destroy()
{
lock (OdeScene.OdeLock)
{
// d.JointDestroy(Amotor);
// Kill the Amotor
d.JointDestroy(Amotor);
//kill the Geometry
_parent_scene.waitForSpaceUnlock(_parent_scene.space);
d.GeomDestroy(Shell);
_parent_scene.geom_name_map.Remove(Shell);
//kill the body
d.BodyDestroy(Body);
}
}
public override void CrossingFailure()
{
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -77,8 +77,11 @@ namespace OpenSim.Region.Physics.POSPlugin
{
// Does nothing right now
}
public override void Dispose()
{
public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID)
}
public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size)
{
POSCharacter act = new POSCharacter();
act.Position = position;
@ -161,8 +164,13 @@ namespace OpenSim.Region.Physics.POSPlugin
for (int i = 0; i < _prims.Count; ++i)
{
if (check_collision(c, _prims[i]))
{
return true;
}
}
return false;
}
@ -195,21 +203,21 @@ namespace OpenSim.Region.Physics.POSPlugin
{
character.Position.Y = 0.1F;
}
else if (character.Position.Y >= 256)
else if (character.Position.Y >= Constants.RegionSize)
{
character.Position.Y = 255.9F;
character.Position.Y = Constants.RegionSize - 0.1f;
}
if (character.Position.X < 0)
{
character.Position.X = 0.1F;
}
else if (character.Position.X >= 256)
else if (character.Position.X >= Constants.RegionSize)
{
character.Position.X = 255.9F;
character.Position.X = Constants.RegionSize - 0.1f;
}
float terrainheight = _heightMap[(int) character.Position.Y*256 + (int) character.Position.X];
float terrainheight = _heightMap[(int)character.Position.Y * Constants.RegionSize + (int)character.Position.X];
if (character.Position.Z + (character._target_velocity.Z*timeStep) < terrainheight + 2)
{
character.Position.Z = terrainheight + 1.0f;
@ -261,18 +269,18 @@ namespace OpenSim.Region.Physics.POSPlugin
{
character.Position.Y = 0.1F;
}
else if (character.Position.Y >= 256)
else if (character.Position.Y >= Constants.RegionSize)
{
character.Position.Y = 255.9F;
character.Position.Y = Constants.RegionSize - 0.1f;
}
if (character.Position.X < 0)
{
character.Position.X = 0.1F;
}
else if (character.Position.X >= 256)
else if (character.Position.X >= Constants.RegionSize)
{
character.Position.X = 255.9F;
character.Position.X = Constants.RegionSize - 0.1f;
}
character._velocity.X = (character.Position.X - oldposX)/timeStep;
@ -282,10 +290,12 @@ namespace OpenSim.Region.Physics.POSPlugin
{
character._velocity.Z = 0;
character._target_velocity.Z = 0;
((PhysicsActor)character).IsColliding = true;
character.RequestPhysicsterseUpdate();
}
else
{
((PhysicsActor)character).IsColliding = false;
character._velocity.Z = (character.Position.Z - oldposZ)/timeStep;
}
}
@ -347,6 +357,16 @@ namespace OpenSim.Region.Physics.POSPlugin
set { return; }
}
public override bool Grabbed
{
set { return; }
}
public override bool Selected
{
set { return; }
}
public override bool IsPhysical
{
get { return false; }
@ -383,6 +403,11 @@ namespace OpenSim.Region.Physics.POSPlugin
set { return; }
}
public override bool Stopped
{
get { return false; }
}
public override PhysicsVector Position
{
get { return _position; }
@ -426,6 +451,11 @@ namespace OpenSim.Region.Physics.POSPlugin
set { _target_velocity = value; }
}
public override float CollisionScore
{
get { return 0f; }
}
public override Quaternion Orientation
{
get { return Quaternion.Identity; }
@ -455,6 +485,10 @@ namespace OpenSim.Region.Physics.POSPlugin
public override void SetMomentum(PhysicsVector momentum)
{
}
public override void CrossingFailure()
{
}
}
public class POSPrim : PhysicsActor
@ -516,6 +550,11 @@ namespace OpenSim.Region.Physics.POSPlugin
set { return; }
}
public override bool Stopped
{
get { return false; }
}
public override PhysicsVector Position
{
get { return _position; }
@ -559,6 +598,11 @@ namespace OpenSim.Region.Physics.POSPlugin
set { _velocity = value; }
}
public override float CollisionScore
{
get { return 0f; }
}
public override Quaternion Orientation
{
get { return _orientation; }
@ -600,5 +644,20 @@ namespace OpenSim.Region.Physics.POSPlugin
get { return false; }
set { return; }
}
public override bool Grabbed
{
set { return; }
}
public override bool Selected
{
set { return; }
}
public override void CrossingFailure()
{
}
}
}

View File

@ -88,9 +88,12 @@ namespace OpenSim.Region.Physics.PhysXPlugin
{
// Does nothing right now
}
public override void Dispose()
{
}
public override PhysicsActor AddAvatar(string avName, PhysicsVector position, uint localID)
public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size)
{
Vec3 pos = new Vec3();
pos.X = position.X;
@ -224,6 +227,16 @@ namespace OpenSim.Region.Physics.PhysXPlugin
set { return; }
}
public override bool Grabbed
{
set { return; }
}
public override bool Selected
{
set { return; }
}
public override bool IsPhysical
{
get { return false; }
@ -266,6 +279,11 @@ namespace OpenSim.Region.Physics.PhysXPlugin
set { m_rotationalVelocity = value; }
}
public override bool Stopped
{
get { return false; }
}
public override PhysicsVector Position
{
get { return _position; }
@ -312,6 +330,11 @@ namespace OpenSim.Region.Physics.PhysXPlugin
set { _velocity = value; }
}
public override float CollisionScore
{
get { return 0f; }
}
public override bool Kinematic
{
get { return false; }
@ -375,6 +398,10 @@ namespace OpenSim.Region.Physics.PhysXPlugin
_position.Y = vec.Y;
_position.Z = vec.Z;
}
public override void CrossingFailure()
{
}
}
@ -410,6 +437,16 @@ namespace OpenSim.Region.Physics.PhysXPlugin
set { return; }
}
public override bool Grabbed
{
set { return; }
}
public override bool Selected
{
set { return; }
}
public override bool ThrottleUpdates
{
get { return false; }
@ -447,6 +484,11 @@ namespace OpenSim.Region.Physics.PhysXPlugin
set { return; }
}
public override bool Stopped
{
get { return false; }
}
public override PhysicsVector Position
{
get
@ -480,6 +522,11 @@ namespace OpenSim.Region.Physics.PhysXPlugin
set { _velocity = value; }
}
public override float CollisionScore
{
get { return 0f; }
}
public override bool Kinematic
{
get { return _prim.Kinematic; }
@ -544,5 +591,9 @@ namespace OpenSim.Region.Physics.PhysXPlugin
{
get { return PhysicsVector.Zero; }
}
public override void CrossingFailure()
{
}
}
}

View File

@ -13,7 +13,7 @@
* 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
* 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
@ -33,62 +33,25 @@ using System.Runtime.Remoting.Lifetime;
namespace OpenSim.Region.ScriptEngine.Common
{
public class Executor : MarshalByRefObject
public class Executor : ExecutorBase
{
// Private instance for each script
private IScript m_Script;
// Cache functions by keeping a reference to them in a dictionary
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)
public Executor(IScript script) : base(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)
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!
//try
//{
if (m_Running == false)
{
// Script is inactive, do not execute!
return;
}
string EventName = m_Script.State() + "_event_" + FunctionName;
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 DEBUG
// Console.WriteLine("ScriptEngine: Script event function name: " + EventName);
//#endif
if (Events.ContainsKey(EventName) == false)
{
@ -112,35 +75,18 @@ namespace OpenSim.Region.ScriptEngine.Common
if (ev == null) // No event by that name!
{
//Console.WriteLine("ScriptEngine Can not find any event named: \"" + EventName + "\"");
//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
//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;
}
}
}

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

@ -13,7 +13,7 @@
* 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
* 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
@ -26,11 +26,16 @@
*
*/
using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
namespace OpenSim.Region.ScriptEngine.Common
{
public interface IScript
{
string State();
Executor Exec { get; }
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; }
}
}

View File

@ -13,7 +13,7 @@
* 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
* 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
@ -31,24 +31,25 @@ using System.Collections.Generic;
using System.Runtime.Remoting.Lifetime;
using System.Threading;
using OpenSim.Region.ScriptEngine.Common;
using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
using integer = System.Int32;
using key = System.String;
using vector = OpenSim.Region.ScriptEngine.Common.LSL_Types.Vector3;
using rotation = OpenSim.Region.ScriptEngine.Common.LSL_Types.Quaternion;
namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
namespace OpenSim.Region.ScriptEngine.Common
{
//[Serializable]
public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, IScript
{
//
// Included as base for any LSL-script that is compiled.
// Any function added here will be accessible to the LSL script. But it must also be added to "LSL_BuiltIn_Commands_Interface" in "OpenSim.Region.ScriptEngine.Common" class.
//
// Security note: This script will be running inside an restricted AppDomain. Currently AppDomain is not very restricted.zxs
// Security note: This script will be running inside an restricted AppDomain. Currently AppDomain is not very restricted.
//
//private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
// Object never expires
public override Object InitializeLifetimeService()
{
@ -65,10 +66,16 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
return lease;
}
public EventQueueManager.Queue_llDetectParams_Struct _llDetectParams;
EventQueueManager.Queue_llDetectParams_Struct IScript.llDetectParams
{
get { return _llDetectParams; }
set { _llDetectParams = value; }
}
private Executor m_Exec;
public Executor Exec
ExecutorBase IScript.Exec
{
get
{
@ -78,24 +85,36 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
}
}
public LSL_BuiltIn_Commands_Interface m_LSL_Functions;
public string SourceCode = "";
private string _Source = String.Empty;
public string Source
{
get
{
return _Source;
}
set { _Source = value; }
}
public LSL_BaseClass()
{
}
public string State()
public string State
{
return m_LSL_Functions.State();
get { return m_LSL_Functions.State; }
set { m_LSL_Functions.State = value; }
}
public void Start(LSL_BuiltIn_Commands_Interface LSL_Functions)
{
m_LSL_Functions = LSL_Functions;
//MainLog.Instance.Notice("ScriptEngine", "LSL_BaseClass.Start() called.");
//m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called.");
// Get this AppDomain's settings and display some of them.
AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
@ -117,6 +136,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
}
//
// DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
//
@ -1225,9 +1246,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
m_LSL_Functions.llEjectFromLand(pest);
}
public void llParseString2List()
public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers)
{
m_LSL_Functions.llParseString2List();
return m_LSL_Functions.llParseString2List(str,separators,spacers);
}
public int llOverMyLand(string id)
@ -1303,7 +1324,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
//
// DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
//
public void llParticleSystem(List<Object> rules)
public void llParticleSystem(LSL_Types.list rules)
{
m_LSL_Functions.llParticleSystem(rules);
}
@ -1810,6 +1831,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
return m_LSL_Functions.llGetParcelDetails(pos, param);
}
public string llStringTrim(string src, int type)
{
return m_LSL_Functions.llStringTrim(src, type);
}
//
// OpenSim Functions
//
@ -1819,6 +1845,36 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
return m_LSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer);
}
public double osTerrainGetHeight(int x, int y)
{
return m_LSL_Functions.osTerrainGetHeight(x, y);
}
public int osTerrainSetHeight(int x, int y, double val)
{
return m_LSL_Functions.osTerrainSetHeight(x, y, val);
}
public int osRegionRestart(double seconds)
{
return m_LSL_Functions.osRegionRestart(seconds);
}
public void osRegionNotice(string msg)
{
m_LSL_Functions.osRegionNotice(msg);
}
public bool osConsoleCommand(string Command)
{
return m_LSL_Functions.osConsoleCommand(Command);
}
public double llList2Float(LSL_Types.list src, int index)
{
return m_LSL_Functions.llList2Float(src, index);
}
// LSL CONSTANTS
public const int TRUE = 1;
public const int FALSE = 0;
@ -1831,6 +1887,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
public const int STATUS_BLOCK_GRAB = 64;
public const int STATUS_DIE_AT_EDGE = 128;
public const int STATUS_RETURN_AT_EDGE = 256;
public const int STATUS_CAST_SHADOWS = 512;
public const int AGENT = 1;
public const int ACTIVE = 2;
public const int PASSIVE = 4;
@ -2033,6 +2090,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
public const int REMOTE_DATA_CHANNEL = 1;
public const int REMOTE_DATA_REQUEST = 2;
public const int REMOTE_DATA_REPLY = 3;
public const int HTTP_METHOD = 0;
public const int HTTP_MIMETYPE = 1;
public const int HTTP_BODY_MAXLENGTH = 2;
public const int HTTP_VERIFY_CERT = 3;
public const int PRIM_MATERIAL = 2;
public const int PRIM_PHYSICS = 3;
@ -2095,6 +2156,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
public const int PRIM_BUMP_SUCTION = 16;
public const int PRIM_BUMP_WEAVE = 17;
public const int PRIM_SCULPT_TYPE_SPHERE = 1;
public const int PRIM_SCULPT_TYPE_TORUS = 2;
public const int PRIM_SCULPT_TYPE_PLANE = 3;
public const int PRIM_SCULPT_TYPE_CYLINDER = 4;
public const int MASK_BASE = 0;
public const int MASK_OWNER = 1;
public const int MASK_GROUP = 2;
@ -2125,9 +2191,22 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
public const double DEG_TO_RAD = 0.01745329238f;
public const double RAD_TO_DEG = 57.29578f;
public const double SQRT2 = 1.414213538f;
public const int STRING_TRIM_HEAD = 1;
public const int STRING_TRIM_TAIL = 2;
public const int STRING_TRIM = 3;
public const int LIST_STAT_RANGE = 0;
public const int LIST_STAT_MIN = 1;
public const int LIST_STAT_MAX = 2;
public const int LIST_STAT_MEAN = 3;
public const int LIST_STAT_MEDIAN = 4;
public const int LIST_STAT_STD_DEV = 5;
public const int LIST_STAT_SUM = 6;
public const int LIST_STAT_SUM_SQUARES = 7;
public const int LIST_STAT_NUM_COUNT = 8;
public const int LIST_STAT_GEOMETRIC_MEAN = 9;
public const int LIST_STAT_HARMONIC_MEAN = 100;
// Can not be public const?
public vector ZERO_VECTOR = new vector(0, 0, 0);
public rotation ZERO_ROTATION = new rotation(0, 0, 0, 0);
public vector ZERO_VECTOR = new vector(0.0, 0.0, 0.0);
public rotation ZERO_ROTATION = new rotation(0.0, 0, 0.0, 1.0);
}
}

View File

@ -25,7 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* Original code: Tedd Hansen */
using System.Collections.Generic;
namespace OpenSim.Region.ScriptEngine.Common
@ -35,7 +35,7 @@ namespace OpenSim.Region.ScriptEngine.Common
// Interface used for loading and executing scripts
string State();
string State { get; set; }
double llSin(double f);
double llCos(double f);
@ -354,6 +354,7 @@ namespace OpenSim.Region.ScriptEngine.Common
//wiki: integer llList2Integer(list src, integer index)
int llList2Integer(LSL_Types.list src, int index);
//wiki: double llList2double(list src, integer index)
double llList2Float(LSL_Types.list src, int index);
double osList2Double(LSL_Types.list src, int index);
//wiki: string llList2String(list src, integer index)
string llList2String(LSL_Types.list src, int index);
@ -409,7 +410,7 @@ namespace OpenSim.Region.ScriptEngine.Common
//wiki: llEjectFromLand(key pest)
void llEjectFromLand(string pest);
void llParseString2List();
LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers);
//wiki: integer llOverMyLand(key id)
int llOverMyLand(string id);
//wiki: key llGetLandOwnerAt(vector pos)
@ -439,7 +440,7 @@ namespace OpenSim.Region.ScriptEngine.Common
//wiki: double llGetRegionFPS()
double llGetRegionFPS();
//wiki: llParticleSystem(List<Object> rules
void llParticleSystem(List<object> rules);
void llParticleSystem(LSL_Types.list rules);
//wiki: llGroundRepel(double height, integer water, double tau)
void llGroundRepel(double height, int water, double tau);
void llGiveInventoryList();
@ -633,8 +634,13 @@ namespace OpenSim.Region.ScriptEngine.Common
int llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide);
//wiki list llGetParcelDetails(vector pos, list params)
LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param);
string llStringTrim(string src, int type);
//OpenSim functions
string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer);
double osTerrainGetHeight(int x, int y);
int osTerrainSetHeight(int x, int y, double val);
int osRegionRestart(double seconds);
void osRegionNotice(string msg);
bool osConsoleCommand(string Command);
}
}

View File

@ -13,7 +13,7 @@
* 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
* 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
@ -28,6 +28,7 @@
using System;
using System.Text.RegularExpressions;
using System.Collections;
namespace OpenSim.Region.ScriptEngine.Common
{
@ -80,6 +81,11 @@ namespace OpenSim.Region.ScriptEngine.Common
return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ">";
}
public static explicit operator string(Vector3 vec)
{
return "<" + vec.x.ToString() + ", " + vec.y.ToString() + ", " + vec.z.ToString() + ">";
}
public static bool operator ==(Vector3 lhs, Vector3 rhs)
{
return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
@ -300,6 +306,11 @@ namespace OpenSim.Region.ScriptEngine.Common
return "<" + x.ToString() + ", " + y.ToString() + ", " + z.ToString() + ", " + s.ToString() + ">";
}
public static explicit operator string(Quaternion r)
{
return "<" + r.x.ToString() + ", " + r.y.ToString() + ", " + r.z.ToString() + ", " + r.s.ToString() + ">";
}
public static bool operator ==(Quaternion lhs, Quaternion rhs)
{
// Return true if the fields match:
@ -354,6 +365,29 @@ namespace OpenSim.Region.ScriptEngine.Common
return new list(tmp);
}
public void Add(object o)
{
object[] tmp;
tmp = new object[m_data.Length + 1];
m_data.CopyTo(tmp, 0);
tmp[m_data.Length] = o;
m_data = tmp;
}
public bool Contains(object o)
{
bool ret = false;
foreach (object i in Data)
{
if (i == o)
{
ret = true;
break;
}
}
return ret;
}
public list GetSublist(int start, int end)
{
Console.WriteLine("GetSublist(" + start.ToString() + "," + end.ToString() + ")");
@ -402,6 +436,199 @@ namespace OpenSim.Region.ScriptEngine.Common
}
}
#region CSV Methods
public static list FromCSV(string csv)
{
return new list(csv.Split(','));
}
public string ToCSV()
{
string ret = "";
foreach(object o in this.Data)
{
if(ret == "")
{
ret = o.ToString();
}
else
{
ret = ret + ", " + o.ToString();
}
}
return ret;
}
#endregion
#region Statistic Methods
public double Min()
{
double minimum = double.PositiveInfinity;
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), out entry))
{
if (entry < minimum) minimum = entry;
}
}
return minimum;
}
public double Max()
{
double maximum = double.NegativeInfinity;
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), out entry))
{
if (entry > maximum) maximum = entry;
}
}
return maximum;
}
public double Range()
{
return (this.Max() / this.Min());
}
public int NumericLength()
{
int count = 0;
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), out entry))
{
count++;
}
}
return count;
}
public static list ToDoubleList(list src)
{
list ret = new list();
double entry;
for (int i = 0; i < src.Data.Length - 1; i++)
{
if (double.TryParse(src.Data[i].ToString(), out entry))
{
ret.Add(entry);
}
}
return ret;
}
public double Sum()
{
double sum = 0;
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), out entry))
{
sum = sum + entry;
}
}
return sum;
}
public double SumSqrs()
{
double sum = 0;
double entry;
for (int i = 0; i < Data.Length; i++)
{
if (double.TryParse(Data[i].ToString(), out entry))
{
sum = sum + Math.Pow(entry, 2);
}
}
return sum;
}
public double Mean()
{
return (this.Sum() / this.NumericLength());
}
public void NumericSort()
{
IComparer Numeric = new NumericComparer();
Array.Sort(Data, Numeric);
}
public void AlphaSort()
{
IComparer Alpha = new AlphaCompare();
Array.Sort(Data, Alpha);
}
public double Median()
{
return Qi(0.5);
}
public double GeometricMean()
{
double ret = 1.0;
list nums = list.ToDoubleList(this);
for (int i = 0; i < nums.Data.Length; i++)
{
ret *= (double)nums.Data[i];
}
return Math.Exp(Math.Log(ret) / (double)nums.Data.Length);
}
public double HarmonicMean()
{
double ret = 0.0;
list nums = list.ToDoubleList(this);
for (int i = 0; i < nums.Data.Length; i++)
{
ret += 1.0 / (double)nums.Data[i];
}
return ((double)nums.Data.Length / ret);
}
public double Variance()
{
double s = 0;
list num = list.ToDoubleList(this);
for (int i = 0; i < num.Data.Length; i++)
{
s += Math.Pow((double)num.Data[i], 2);
}
return (s - num.Data.Length * Math.Pow(num.Mean(), 2)) / (num.Data.Length - 1);
}
public double StdDev()
{
return Math.Sqrt(this.Variance());
}
public double Qi(double i)
{
list j = this;
j.NumericSort();
double ret;
if (Math.Ceiling(this.Length * i) == this.Length * i)
{
return (double)((double)j.Data[(int)(this.Length * i - 1)] + (double)j.Data[(int)(this.Length * i)]) / 2;
}
else
{
return (double)j.Data[((int)(Math.Ceiling(this.Length * i))) - 1];
}
}
#endregion
public string ToPrettyString()
{
string output;
@ -426,13 +653,50 @@ namespace OpenSim.Region.ScriptEngine.Common
return output;
}
public class AlphaCompare : IComparer
{
int IComparer.Compare(object x, object y)
{
return string.Compare(x.ToString(), y.ToString());
}
}
public class NumericComparer : IComparer
{
int IComparer.Compare(object x, object y)
{
double a;
double b;
if (!double.TryParse(x.ToString(), out a))
{
a = 0.0;
}
if (!double.TryParse(y.ToString(), out b))
{
b = 0.0;
}
if (a < b)
{
return -1;
}
else if (a == b)
{
return 0;
}
else
{
return 1;
}
}
}
public override string ToString()
{
string output;
output = "";
output = String.Empty;
if (m_data.Length == 0)
{
return "";
return String.Empty;
}
foreach (object o in m_data)
{
@ -442,6 +706,20 @@ namespace OpenSim.Region.ScriptEngine.Common
}
public static explicit operator string(list l)
{
string output;
output = String.Empty;
if (l.m_data.Length == 0)
{
return String.Empty;
}
foreach (object o in l.m_data)
{
output = output + o.ToString();
}
return output;
}
}
//

View File

@ -1,3 +1,31 @@
/*
* 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;
@ -10,7 +38,7 @@ using System.Runtime.InteropServices;
[assembly : AssemblyConfiguration("")]
[assembly : AssemblyCompany("")]
[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.Common")]
[assembly : AssemblyCopyright("Copyright © 2007")]
[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2008")]
[assembly : AssemblyTrademark("")]
[assembly : AssemblyCulture("")]

View File

@ -13,7 +13,7 @@
* 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
* 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
@ -30,13 +30,12 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL;
using OpenSim.Region.ScriptEngine.Common;
namespace OpenSim.Region.ScriptEngine.DotNetEngine
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
{
public class AppDomainManager
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"
@ -47,7 +46,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// 4. Unload AppDomain completely when all scripts in it has stopped
//
private int maxScriptsPerAppDomain = 1;
/// <summary>
@ -84,11 +82,17 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
private object getLock = new object(); // Mutex
private object freeLock = new object(); // Mutex
//private ScriptEngine m_scriptEngine;
private ScriptEngine m_scriptEngine;
//public AppDomainManager(ScriptEngine scriptEngine)
public AppDomainManager()
public AppDomainManager(ScriptEngine scriptEngine)
{
//m_scriptEngine = scriptEngine;
m_scriptEngine = scriptEngine;
ReadConfig();
}
public void ReadConfig()
{
maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1);
}
/// <summary>
@ -97,7 +101,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
/// <returns>Free AppDomain</returns>
private AppDomainStructure GetFreeAppDomain()
{
Console.WriteLine("Finding free AppDomain");
// Console.WriteLine("Finding free AppDomain");
lock (getLock)
{
// Current full?
@ -115,9 +119,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
currentAD.CurrentAppDomain = PrepareNewAppDomain();
}
Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
// Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
return currentAD;
} // lock
}
}
private int AppDomainNameCount;
@ -142,7 +146,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
Console.WriteLine("Loading: " +
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"));
@ -167,33 +171,33 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// 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
Console.WriteLine("Found empty AppDomain, unloading");
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");
m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory");
#endif
}
}
} // foreach
} // lock
}
}
}
public LSL_BaseClass LoadScript(string FileName)
public IScript 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)
#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++;
@ -211,7 +215,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
{
lock (freeLock)
{
Console.WriteLine("Stopping script in AppDomain");
#if DEBUG
m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Stopping script in AppDomain");
#endif
// Check if it is current AppDomain
if (currentAD.CurrentAppDomain == ad)
{
@ -229,10 +235,20 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
ads.ScriptsWaitingUnload++;
break;
}
} // foreach
} // lock
}
}
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

@ -25,8 +25,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* Original code: Tedd Hansen */
namespace OpenSim.Region.ScriptEngine.DotNetEngine
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
{
public static class Common
{
@ -35,23 +35,23 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// This class just contains some static log stuff used for debugging.
//public delegate void SendToDebugEventDelegate(string Message);
//public delegate void SendToLogEventDelegate(string Message);
//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)
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);
mySE.Log.Info("[" + mySE.ScriptEngineName + "]: Debug: " + message);
//SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message);
}
public static void SendToLog(string 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);
mySE.Log.Info("[" + mySE.ScriptEngineName + "]: LOG: " + message);
//SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + message);
}
}
}

View File

@ -25,20 +25,20 @@
* 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
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
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:
@ -55,36 +55,48 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
private ScriptEngine myScriptEngine;
//public IScriptHost TEMP_OBJECT_ID;
public EventManager(ScriptEngine _ScriptEngine)
public EventManager(ScriptEngine _ScriptEngine, bool performHookUp)
{
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
ReadConfig();
// Hook up a test event to our test form
myScriptEngine.Log.Verbose("ScriptEngine", "Hooking up to server events");
// 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_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});
myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", EventQueueManager.llDetectNull, 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);
@ -92,10 +104,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
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,
@ -104,134 +112,177 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
}
// 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_entry() { } //
public void state_exit(uint localID, LLUUID itemID)
{
myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_exit", EventQueueManager.llDetectNull);
}
//public void touch_start(uint localID, LLUUID itemID) { }
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,5 +1,37 @@
using libsecondlife;
/*
* 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
{
@ -48,5 +80,11 @@ namespace OpenSim.Region.ScriptEngine.Common
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

@ -13,7 +13,7 @@
* 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
* 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
@ -28,15 +28,18 @@
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.
@ -44,82 +47,327 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
// 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)
internal enum enumCompileType
{
switch (Path.GetExtension(LSOFileName).ToLower())
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)
{
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.");
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 CompileFromLSLText(string Script)
public string PerformScriptCompile(string Script)
{
if (Script.Substring(0, 4).ToLower() == "//c#")
enumCompileType l = DefaultCompileLanguage;
if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture))
l = enumCompileType.cs;
if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture))
{
return CompileFromCSText(Script);
l = enumCompileType.vb;
// We need to remove //vb, it won't compile with that
Script = Script.Substring(4, Script.Length - 4);
}
else
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()))
{
return CompileFromCSText(LSL_Converter.Convert(Script));
// 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 CS script to .Net assembly (.dll)
/// Compile .NET script to .Net assembly (.dll)
/// </summary>
/// <param name="Script">CS script</param>
/// <returns>Filename to .dll assembly</returns>
public string CompileFromCSText(string Script)
internal string CompileFromDotNetText(string Script, enumCompileType lang)
{
string ext = "." + lang.ToString();
// Output assembly name
scriptCompileCounter++;
string OutFile =
Path.Combine("ScriptEngines",
"DotNetScript_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll");
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)
catch (Exception e) // NOTLEGIT - Should be just catching FileIOException
{
Console.WriteLine("Exception attempting to delete old compiled script: " + e.ToString());
//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", "debug_" + Path.GetFileNameWithoutExtension(OutFile) + ".cs"), Script);
Path.Combine("ScriptEngines", srcFileName),
Script);
}
catch
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())
{
@ -136,24 +384,57 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
//parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment");
parameters.GenerateExecutable = false;
parameters.OutputAssembly = OutFile;
parameters.IncludeDebugInformation = false;
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, Script);
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
// TODO: Return errors to user somehow
//
// WARNINGS AND ERRORS
//
if (results.Errors.Count > 0)
{
string errtext = "";
string errtext = String.Empty;
foreach (CompilerError CompErr in results.Errors)
{
errtext += "Line number " + (CompErr.Line - 1) +
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

@ -13,7 +13,7 @@
* 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
* 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
@ -28,6 +28,7 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System;
namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
{
@ -58,7 +59,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
public string Convert(string Script)
{
quotes.Clear();
string Return = "";
string Return = System.String.Empty;
Script = " \r\n" + Script;
//
@ -72,13 +73,14 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
// 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 = "";
// 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 = "";
string quote = System.String.Empty;
bool last_was_escape = false;
int quote_replaced_count = 0;
for (int p = 0; p < Script.Length; p++)
@ -97,7 +99,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
}
else
{
if (quote == "")
if (quote == System.String.Empty)
{
// We didn't replace quote, probably because of empty string?
_Script += quote_replacement_string +
@ -107,7 +109,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
quotes.Add(
quote_replacement_string +
quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote);
quote = "";
quote = System.String.Empty;
}
break;
}
@ -151,10 +153,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
//
int ilevel = 0;
int lastlevel = 0;
string ret = "";
string cache = "";
string ret = System.String.Empty;
string cache = System.String.Empty;
bool in_state = false;
string current_statename = "";
string current_statename = System.String.Empty;
for (int p = 0; p < Script.Length; p++)
{
C = Script.Substring(p, 1);
@ -191,7 +193,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
}
ret += cache;
cache = "";
cache = String.Empty;
}
if (ilevel == 0 && lastlevel == 1)
{
@ -199,7 +201,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
if (in_state == true)
{
cache = cache.Remove(cache.Length - 1, 1);
//cache = Regex.Replace(cache, "}$", "", RegexOptions.Multiline | RegexOptions.Singleline);
//cache = Regex.Replace(cache, "}$", String.Empty, RegexOptions.Multiline | RegexOptions.Singleline);
//Replace function names
// void dataserver(key query_id, string data) {
@ -213,9 +215,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
}
ret += cache;
cache = "";
cache = String.Empty;
in_state = true;
current_statename = "";
current_statename = String.Empty;
}
break;
@ -223,10 +225,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
lastlevel = ilevel;
}
ret += cache;
cache = "";
cache = String.Empty;
Script = ret;
ret = "";
ret = String.Empty;
foreach (string key in dataTypes.Keys)
@ -250,15 +252,15 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
// 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*\([^\)]*\)[^;]*\{)",
@"^(\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)",
Regex.Replace(Script, @"<([^,>;]*,[^,>;\)]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Quaternion($1)",
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
Script =
Regex.Replace(Script, @"<([^,>;\)]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Vector3($1)",
Regex.Replace(Script, @"<([^,>;]*,[^,>;\)]*,[^,>;\)]*)>", @"new LSL_Types.Vector3($1)",
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
// Replace List []'s
@ -269,10 +271,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
// Replace (string) to .ToString() //
Script =
Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_]+(\s*\([^\)]*\))?)", @"$1.ToString()",
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)",
Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.Parse($2)",
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
@ -287,36 +289,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
// 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 = String.Empty;// +
//"using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;";
Return += "" +
"namespace SecondLife { ";
Return += "" +
//"[Serializable] " +
"public class Script : OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass { ";
Return += @"public Script() { } ";
//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";
//Return += "} }\r\n";
quotes.Clear();

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,3 +1,31 @@
/*
* 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;
@ -10,7 +38,7 @@ using System.Runtime.InteropServices;
[assembly : AssemblyConfiguration("")]
[assembly : AssemblyCompany("")]
[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.DotNetEngine")]
[assembly : AssemblyCopyright("Copyright © 2007")]
[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2008")]
[assembly : AssemblyTrademark("")]
[assembly : AssemblyCulture("")]

View File

@ -29,90 +29,28 @@
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 class ScriptEngine : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptEngine
{
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()
// We need to override a few things for our DotNetEngine
public override void Initialise(Scene scene, IConfigSource config)
{
//Common.SendToDebug("ScriptEngine Object Initialized");
Common.mySE = this;
ConfigSource = config;
InitializeEngine(scene, config, true, GetScriptManager());
}
public LogBase Log
public override OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.ScriptManager _GetScriptManager()
{
get { return m_log; }
return new ScriptManager(this);
}
public void InitializeEngine(Scene Sceneworld, LogBase logger)
public override string ScriptEngineName
{
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
get { return "ScriptEngine.DotNetEngine"; }
}
}
}

View File

@ -26,300 +26,72 @@
*
*/
/* 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;
using OpenSim.Region.ScriptEngine.Common;
using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
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
public class ScriptManager : OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.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 ScriptManager(Common.ScriptEngineBase.ScriptEngine scriptEngine)
: base(scriptEngine)
{
public uint localID;
public LLUUID itemID;
public string script;
public LUType Action;
base.m_scriptEngine = scriptEngine;
}
private Compiler.LSL.Compiler LSLCompiler;
public override void Initialize()
{
// Create our compiler
LSLCompiler = new Compiler.LSL.Compiler(m_scriptEngine);
}
private enum LUType
// 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)
{
Unknown = 0,
Load = 1,
Unload = 2
}
m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID);
// 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 = "";
string ScriptSource = String.Empty;
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;
}
ScriptSource = LSLCompiler.PerformScriptCompile(Script);
#if DEBUG
long before;
before = GC.GetTotalMemory(true);
#endif
LSL_BaseClass CompiledScript;
IScript CompiledScript;
CompiledScript = m_scriptEngine.m_AppDomainManager.LoadScript(ScriptSource);
#if DEBUG
Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before);
m_scriptEngine.Log.DebugFormat("[" + m_scriptEngine.ScriptEngineName + "]: Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before);
#endif
CompiledScript.SourceCode = ScriptSource;
CompiledScript.Source = Script;
// Add it to our script memstruct
SetScript(localID, itemID, CompiledScript);
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.
@ -331,11 +103,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
CompiledScript.Start(LSLB);
// Fire the first start-event
m_scriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_entry", new object[] {});
m_scriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_entry", EventQueueManager.llDetectNull, new object[] { });
}
catch (Exception e)
catch (Exception e) // LEGIT: User Scripting
{
//m_scriptEngine.Log.Error("ScriptEngine", "Error compiling script: " + e.ToString());
//m_scriptEngine.Log.Error("[ScriptEngine]: Error compiling script: " + e.ToString());
try
{
// DISPLAY ERROR INWORLD
@ -345,111 +117,48 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, m_host.AbsolutePosition,
m_host.Name, m_host.UUID);
}
catch (Exception e2)
catch (Exception e2) // LEGIT: User Scripting
{
m_scriptEngine.Log.Error("ScriptEngine", "Error displaying error in-world: " + e2.ToString());
m_scriptEngine.Log.Error("ScriptEngine",
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());
}
}
}
}
private void _StopScript(uint localID, LLUUID itemID)
{
lock (startStopLock)
public override void _StopScript(uint localID, LLUUID itemID)
{
// Stop script
Console.WriteLine("Stop script localID: " + localID + " LLUID: " + itemID.ToString());
#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_LSLLongCmdHandler.RemoveScript(localID, itemID);
m_scriptEngine.m_ASYNCLSLCommandManager.RemoveScript(localID, itemID);
LSL_BaseClass LSLBC = GetScript(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();
m_scriptEngine.m_ScriptManager.GetScript(localID, itemID).Exec.StopScript();
// Remove from internal structure
RemoveScript(localID, itemID);
m_scriptEngine.m_ScriptManager.RemoveScript(localID, itemID);
// Tell AppDomain that we have stopped script
m_scriptEngine.m_AppDomainManager.StopScript(ad);
}
catch (Exception e)
catch (Exception e) // LEGIT: User Scripting
{
Console.WriteLine("Exception stopping script localID: " + localID + " LLUID: " + itemID.ToString() +
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: 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
}
}

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

@ -13,7 +13,7 @@
* 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
* 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
@ -27,43 +27,24 @@
*/
using System;
using System.Collections.Generic;
using System.IO;
using Rail.Reflect;
using Rail.Transformation;
using System.Text;
using OpenSim.Region.ScriptEngine.LSOEngine.LSO;
namespace OpenSim.Region.ScriptEngine.DotNetEngine
namespace OpenSim.Region.ScriptEngine.LSOEngine
{
/// <summary>
/// Tedds Sandbox for RAIL/microtrheading. This class is only for testing purposes!
/// Its offspring will be the actual implementation.
/// This class encapsulated an LSO file and contains execution-specific data
/// </summary>
internal class TempDotNetMicroThreadingCodeInjector
public class LSOScript
{
public static string TestFix(string FileName)
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)
{
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;
}
}
}

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

@ -26,6 +26,7 @@
*
*/
/* Original code: Tedd Hansen */
namespace OpenSim.Region.ScriptEngine.RemoteServer
{
public static class Common
@ -43,14 +44,14 @@ namespace OpenSim.Region.ScriptEngine.RemoteServer
public static void SendToDebug(string Message)
{
//if (Debug == true)
mySE.Log.Verbose("ScriptEngine", "Debug: " + Message);
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.Verbose("ScriptEngine", "LOG: " + Message);
mySE.Log.Info("[ScriptEngine]: LOG: " + Message);
//SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
}
}

View File

@ -26,10 +26,12 @@
*
*/
/* 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
{
@ -39,42 +41,62 @@ namespace OpenSim.Region.ScriptEngine.RemoteServer
[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;
myScriptEngine.Log.Verbose("RemoteEngine", "Hooking up to server events");
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.Verbose("RemoteEngine", "Creating new script (with connection)");
ScriptServerInterfaces.ServerRemotingObject obj = myScriptEngine.m_RemoteServer.Connect("localhost", 1234);
myScriptEngine.Log.Info("[RemoteEngine]: Creating new script (with connection)");
remoteScript.Add(localID, obj);
//remoteScript[localID].Events.OnRezScript(localID, itemID, script);
// 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!
@ -237,6 +259,5 @@ namespace OpenSim.Region.ScriptEngine.RemoteServer
//{
// remoteScript[localID].Events.http_response(localID, itemID);
//}
}
}

View File

@ -1,3 +1,31 @@
/*
* 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;
@ -10,7 +38,7 @@ using System.Runtime.InteropServices;
[assembly : AssemblyConfiguration("")]
[assembly : AssemblyCompany("")]
[assembly : AssemblyProduct("OpenSim.Region.ScriptEngine.RemoteServer")]
[assembly : AssemblyCopyright("Copyright © 2007")]
[assembly : AssemblyCopyright("Copyright © OpenSimulator.org Developers 2007-2008")]
[assembly : AssemblyTrademark("")]
[assembly : AssemblyCulture("")]

View File

@ -1,4 +1,32 @@
using System;
/*
* 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;
@ -13,22 +41,19 @@ namespace OpenSim.Region.ScriptEngine.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
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
{
try
{
// Create an instance of the remote object
ScriptServerInterfaces.ServerRemotingObject obj = (ScriptServerInterfaces.ServerRemotingObject)Activator.GetObject(
typeof(ScriptServerInterfaces.ServerRemotingObject),
@ -53,7 +78,6 @@ namespace OpenSim.Region.ScriptEngine.RemoteServer
System.Console.WriteLine("Error: unable to connect to server");
}
return null;
}
}
}

View File

@ -26,6 +26,7 @@
*
*/
/* Original code: Tedd Hansen */
using System;
using Nini.Config;
using OpenSim.Framework.Console;
@ -41,28 +42,27 @@ namespace OpenSim.Region.ScriptEngine.RemoteServer
[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
private LogBase m_log;
public ScriptEngine()
{
Common.mySE = this;
}
public LogBase Log
public log4net.ILog Log
{
get { return m_log; }
}
public void InitializeEngine(Scene Sceneworld, LogBase logger)
public void InitializeEngine(Scene Sceneworld)
{
World = Sceneworld;
m_log = logger;
Log.Verbose("ScriptEngine", "RemoteEngine (Remote Script Server) initializing");
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();
@ -74,12 +74,11 @@ namespace OpenSim.Region.ScriptEngine.RemoteServer
// We are shutting down
}
#region IRegionModule
public void Initialise(Scene scene, IConfigSource config)
{
InitializeEngine(scene, MainLog.Instance);
InitializeEngine(scene);
}
public void PostInitialise()
@ -101,6 +100,5 @@ namespace OpenSim.Region.ScriptEngine.RemoteServer
}
#endregion
}
}