Add an extension to allow registering multiple interfaces of a type with

Scene. Make the script engines check that the engine name in the
//Engine:language comment is a valid engine and treat it as a normal
comment if it's not.
//DotNetEngine: needs to be written as //ScriptEngine.DotNetEngine: now, since
that is it's real internal name. //XEngine: still works
0.6.0-stable
Melanie Thielker 2008-09-25 17:26:32 +00:00
parent 339671afc6
commit f11107821e
11 changed files with 202 additions and 84 deletions

View File

@ -65,5 +65,6 @@ namespace OpenSim.Framework
string GetCapsPath(UUID agentId); string GetCapsPath(UUID agentId);
T RequestModuleInterface<T>(); T RequestModuleInterface<T>();
T[] RequestModuleInterfaces<T>();
} }
} }

View File

@ -178,6 +178,7 @@ namespace OpenSim.Region.Environment.Scenes
remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false); remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
return UUID.Zero; return UUID.Zero;
} }
remoteClient.SendAgentAlertMessage("Notecard saved", false);
} }
else if ((InventoryType) item.InvType == InventoryType.LSL) else if ((InventoryType) item.InvType == InventoryType.LSL)
{ {
@ -186,6 +187,7 @@ namespace OpenSim.Region.Environment.Scenes
remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
return UUID.Zero; return UUID.Zero;
} }
remoteClient.SendAgentAlertMessage("Script saved", false);
} }
AssetBase asset = AssetBase asset =
@ -287,6 +289,10 @@ namespace OpenSim.Region.Environment.Scenes
// //
part.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine); part.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine);
} }
else
{
remoteClient.SendAgentAlertMessage("Script saved", false);
}
} }
/// <summary> /// <summary>

View File

@ -124,7 +124,7 @@ namespace OpenSim.Region.Environment.Scenes
{ {
get { return m_modules; } get { return m_modules; }
} }
protected Dictionary<Type, object> ModuleInterfaces = new Dictionary<Type, object>(); protected Dictionary<Type, List<object> > ModuleInterfaces = new Dictionary<Type, List<object> >();
protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>(); protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>();
protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>(); protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>();
@ -3025,10 +3025,27 @@ namespace OpenSim.Region.Environment.Scenes
{ {
if (!ModuleInterfaces.ContainsKey(typeof(M))) if (!ModuleInterfaces.ContainsKey(typeof(M)))
{ {
ModuleInterfaces.Add(typeof(M), mod); List<Object> l = new List<Object>();
l.Add(mod);
ModuleInterfaces.Add(typeof(M), l);
} }
} }
public void StackModuleInterface<M>(M mod)
{
List<Object> l;
if (ModuleInterfaces.ContainsKey(typeof(M)))
l = ModuleInterfaces[typeof(M)];
else
l = new List<Object>();
if (l.Contains(mod))
return;
l.Add(mod);
ModuleInterfaces[typeof(M)] = l;
}
/// <summary> /// <summary>
/// For the given interface, retrieve the region module which implements it. /// For the given interface, retrieve the region module which implements it.
/// </summary> /// </summary>
@ -3037,7 +3054,7 @@ namespace OpenSim.Region.Environment.Scenes
{ {
if (ModuleInterfaces.ContainsKey(typeof(T))) if (ModuleInterfaces.ContainsKey(typeof(T)))
{ {
return (T)ModuleInterfaces[typeof(T)]; return (T)ModuleInterfaces[typeof(T)][0];
} }
else else
{ {
@ -3045,6 +3062,22 @@ namespace OpenSim.Region.Environment.Scenes
} }
} }
public override T[] RequestModuleInterfaces<T>()
{
if (ModuleInterfaces.ContainsKey(typeof(T)))
{
List<T> ret = new List<T>();
foreach(Object o in ModuleInterfaces[typeof(T)])
ret.Add((T)o);
return ret.ToArray();
}
else
{
return new T[] { default(T) };
}
}
public void SetObjectCapacity(int objects) public void SetObjectCapacity(int objects)
{ {
if (m_statsReporter != null) if (m_statsReporter != null)
@ -3628,7 +3661,7 @@ namespace OpenSim.Region.Environment.Scenes
m_eventManager.TriggerNotAtTargetEvent(localID); m_eventManager.TriggerNotAtTargetEvent(localID);
} }
private bool scriptDanger(SceneObjectPart part,Vector3 pos) private bool ScriptDanger(SceneObjectPart part,Vector3 pos)
{ {
ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
if (part != null) if (part != null)
@ -3684,12 +3717,12 @@ namespace OpenSim.Region.Environment.Scenes
} }
} }
public bool scriptDanger(uint localID, Vector3 pos) public bool ScriptDanger(uint localID, Vector3 pos)
{ {
SceneObjectPart part = GetSceneObjectPart(localID); SceneObjectPart part = GetSceneObjectPart(localID);
if (part != null) if (part != null)
{ {
return scriptDanger(part, pos); return ScriptDanger(part, pos);
} }
else else
{ {
@ -3697,19 +3730,19 @@ namespace OpenSim.Region.Environment.Scenes
} }
} }
public bool pipeEventsForScript(uint localID) public bool PipeEventsForScript(uint localID)
{ {
SceneObjectPart part = GetSceneObjectPart(localID); SceneObjectPart part = GetSceneObjectPart(localID);
if (part != null) if (part != null)
{ {
// Changed so that child prims of attachments return scriptDanger for their parent, so that // Changed so that child prims of attachments return ScriptDanger for their parent, so that
// their scripts will actually run. // their scripts will actually run.
// -- Leaf, Tue Aug 12 14:17:05 EDT 2008 // -- Leaf, Tue Aug 12 14:17:05 EDT 2008
SceneObjectPart parent = part.ParentGroup.RootPart; SceneObjectPart parent = part.ParentGroup.RootPart;
if (parent != null && parent.IsAttachment) if (parent != null && parent.IsAttachment)
return scriptDanger(parent, parent.GetWorldPosition()); return ScriptDanger(parent, parent.GetWorldPosition());
else else
return scriptDanger(part, part.GetWorldPosition()); return ScriptDanger(part, part.GetWorldPosition());
} }
else else
{ {

View File

@ -225,5 +225,10 @@ namespace OpenSim.Region.Environment.Scenes
{ {
return default(T); return default(T);
} }
public virtual T[] RequestModuleInterfaces<T>()
{
return new T[] { default(T) };
}
} }
} }

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 OpenSim.Framework;
using OpenMetaverse;
namespace OpenSim.Region.Interfaces
{
public interface IScriptModule
{
string ScriptEngineName { get; }
}
}

View File

@ -215,6 +215,12 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
public void OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine) public void OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine)
{ {
List<IScriptModule> engines = new List<IScriptModule>(myScriptEngine.World.RequestModuleInterfaces<IScriptModule>());
List<string> names = new List<string>();
foreach (IScriptModule m in engines)
names.Add(m.ScriptEngineName);
int lineEnd = script.IndexOf('\n'); int lineEnd = script.IndexOf('\n');
if (lineEnd != 1) if (lineEnd != 1)
@ -224,8 +230,13 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
int colon = firstline.IndexOf(':'); int colon = firstline.IndexOf(':');
if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1) if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1)
{ {
engine = firstline.Substring(2, colon-2); string engineName = firstline.Substring(2, colon-2);
script = "//" + script.Substring(script.IndexOf(':')+1);
if (names.Contains(engineName))
{
engine = engineName;
script = "//" + script.Substring(script.IndexOf(':')+1);
}
} }
} }

View File

@ -282,7 +282,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
// QIS.functionName); // QIS.functionName);
#endif #endif
// Only pipe event if land supports it. // Only pipe event if land supports it.
if (m_ScriptEngine.World.pipeEventsForScript(QIS.localID)) if (m_ScriptEngine.World.PipeEventsForScript(QIS.localID))
{ {
LastExecutionStarted = DateTime.Now.Ticks; LastExecutionStarted = DateTime.Now.Ticks;
KillCurrentScript = false; KillCurrentScript = false;

View File

@ -30,6 +30,7 @@ using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
using OpenSim.Region.Interfaces;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Interfaces;
@ -43,7 +44,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
/// </summary> /// </summary>
/// ///
[Serializable] [Serializable]
public abstract class ScriptEngine : IRegionModule, ScriptServerInterfaces.ScriptEngine, iScriptEngineFunctionModule, IEventReceiver public abstract class ScriptEngine : IRegionModule, IScriptModule, ScriptServerInterfaces.ScriptEngine, iScriptEngineFunctionModule, IEventReceiver
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -126,8 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\""); m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\"");
ReadConfig(); ReadConfig();
// Should we iterate the region for scripts that needs starting? m_Scene.StackModuleInterface<IScriptModule>(this);
// Or can we assume we are loaded before anything else so we can use proper events?
} }
public void PostInitialise() public void PostInitialise()

View File

@ -5114,7 +5114,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Integer llScriptDanger(LSL_Vector pos) public LSL_Integer llScriptDanger(LSL_Vector pos)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
bool result = World.scriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z));
if (result) if (result)
{ {
return 1; return 1;

View File

@ -567,85 +567,89 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
} }
else else
{ {
SceneObjectPart part = m_Engine.World.GetSceneObjectPart( if (m_Engine.World.PipeEventsForScript(m_LocalID) ||
m_LocalID); data.EventName == "control") // Don't freeze avies!
// m_Engine.Log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
// m_PrimName, m_ScriptName, data.EventName, m_State);
try
{ {
m_CurrentEvent = data.EventName; SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
m_EventStart = DateTime.Now; m_LocalID);
m_InEvent = true; // m_Engine.Log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
// m_PrimName, m_ScriptName, data.EventName, m_State);
m_Script.ExecuteEvent(State, data.EventName, data.Params); try
m_InEvent = false;
m_CurrentEvent = String.Empty;
if (m_SaveState)
{ {
// This will be the very first event we deliver m_CurrentEvent = data.EventName;
// (state_entry) in defualt state m_EventStart = DateTime.Now;
// m_InEvent = true;
SaveState(m_Assembly); m_Script.ExecuteEvent(State, data.EventName, data.Params);
m_SaveState = false; m_InEvent = false;
} m_CurrentEvent = String.Empty;
}
catch (Exception e)
{
m_InEvent = false;
m_CurrentEvent = String.Empty;
if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException)))) if (m_SaveState)
{
if (e is System.Threading.ThreadAbortException)
{ {
lock (m_EventQueue) // This will be the very first event we deliver
// (state_entry) in defualt state
//
SaveState(m_Assembly);
m_SaveState = false;
}
}
catch (Exception e)
{
m_InEvent = false;
m_CurrentEvent = String.Empty;
if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException))))
{
if (e is System.Threading.ThreadAbortException)
{ {
if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) lock (m_EventQueue)
{ {
m_CurrentResult=m_Engine.QueueEventHandler(this); if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown))
} {
else m_CurrentResult=m_Engine.QueueEventHandler(this);
{ }
m_CurrentResult = null; else
{
m_CurrentResult = null;
}
} }
m_DetectParams = null;
return 0;
} }
m_DetectParams = null; try
{
return 0; // DISPLAY ERROR INWORLD
string text = "Runtime error:\n" + e.InnerException.ToString();
if (text.Length > 1000)
text = text.Substring(0, 1000);
m_Engine.World.SimChat(Utils.StringToBytes(text),
ChatTypeEnum.DebugChannel, 2147483647,
part.AbsolutePosition,
part.Name, part.UUID, false);
}
catch (Exception e2) // LEGIT: User Scripting
{
m_Engine.Log.Error("[Script]: "+
"Error displaying error in-world: " +
e2.ToString());
m_Engine.Log.Error("[Script]: " +
"Errormessage: Error compiling script:\r\n" +
e.ToString());
}
} }
else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
try
{ {
// DISPLAY ERROR INWORLD m_InSelfDelete = true;
string text = "Runtime error:\n" + e.InnerException.ToString(); if (part != null && part.ParentGroup != null)
if (text.Length > 1000) m_Engine.World.DeleteSceneObject(part.ParentGroup);
text = text.Substring(0, 1000);
m_Engine.World.SimChat(Utils.StringToBytes(text),
ChatTypeEnum.DebugChannel, 2147483647,
part.AbsolutePosition,
part.Name, part.UUID, false);
} }
catch (Exception e2) // LEGIT: User Scripting
{
m_Engine.Log.Error("[Script]: "+
"Error displaying error in-world: " +
e2.ToString());
m_Engine.Log.Error("[Script]: " +
"Errormessage: Error compiling script:\r\n" +
e.ToString());
}
}
else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
{
m_InSelfDelete = true;
if (part != null && part.ParentGroup != null)
m_Engine.World.DeleteSceneObject(part.ParentGroup);
} }
} }
} }

View File

@ -39,6 +39,7 @@ using log4net;
using Nini.Config; using Nini.Config;
using Amib.Threading; using Amib.Threading;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Interfaces;
using OpenSim.Region.Environment; using OpenSim.Region.Environment;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
@ -50,7 +51,7 @@ using OpenSim.Region.ScriptEngine.Interfaces;
namespace OpenSim.Region.ScriptEngine.XEngine namespace OpenSim.Region.ScriptEngine.XEngine
{ {
public class XEngine : IRegionModule, IScriptEngine public class XEngine : IRegionModule, IScriptModule, IScriptEngine
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -213,6 +214,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
// //
SetupEngine(m_MinThreads, m_MaxThreads, m_IdleTimeout, m_Prio, SetupEngine(m_MinThreads, m_MaxThreads, m_IdleTimeout, m_Prio,
m_MaxScriptQueue, m_StackSize); m_MaxScriptQueue, m_StackSize);
m_Scene.StackModuleInterface<IScriptModule>(this);
} }
public void PostInitialise() public void PostInitialise()
@ -331,6 +334,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
public void OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine) public void OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine)
{ {
List<IScriptModule> engines = new List<IScriptModule>(m_Scene.RequestModuleInterfaces<IScriptModule>());
List<string> names = new List<string>();
foreach (IScriptModule m in engines)
names.Add(m.ScriptEngineName);
int lineEnd = script.IndexOf('\n'); int lineEnd = script.IndexOf('\n');
if (lineEnd != 1) if (lineEnd != 1)
@ -340,8 +349,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
int colon = firstline.IndexOf(':'); int colon = firstline.IndexOf(':');
if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1) if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1)
{ {
engine = firstline.Substring(2, colon-2); string engineName = firstline.Substring(2, colon-2);
script = "//" + script.Substring(script.IndexOf(':')+1);
if (names.Contains(engineName))
{
engine = engineName;
script = "//" + script.Substring(script.IndexOf(':')+1);
}
} }
} }
@ -454,14 +468,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
// m_log.DebugFormat("[XEngine] Compiling script {0} ({1})", // m_log.DebugFormat("[XEngine] Compiling script {0} ({1})",
// item.Name, itemID.ToString()); // item.Name, itemID.ToString());
ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
string assembly = ""; string assembly = "";
try try
{ {
assembly = m_Compiler.PerformScriptCompile(script, assembly = m_Compiler.PerformScriptCompile(script,
assetID.ToString()); assetID.ToString());
if (presence != null)
presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
} }
catch (Exception e) catch (Exception e)
{ {
if (presence != null)
presence.ControllingClient.SendAgentAlertMessage("Script saved with errors, check debug window!", false);
try try
{ {
// DISPLAY ERROR INWORLD // DISPLAY ERROR INWORLD