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

View File

@ -124,7 +124,7 @@ namespace OpenSim.Region.Environment.Scenes
{
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, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>();
@ -3025,10 +3025,27 @@ namespace OpenSim.Region.Environment.Scenes
{
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>
/// For the given interface, retrieve the region module which implements it.
/// </summary>
@ -3037,7 +3054,7 @@ namespace OpenSim.Region.Environment.Scenes
{
if (ModuleInterfaces.ContainsKey(typeof(T)))
{
return (T)ModuleInterfaces[typeof(T)];
return (T)ModuleInterfaces[typeof(T)][0];
}
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)
{
if (m_statsReporter != null)
@ -3628,7 +3661,7 @@ namespace OpenSim.Region.Environment.Scenes
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);
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);
if (part != null)
{
return scriptDanger(part, pos);
return ScriptDanger(part, pos);
}
else
{
@ -3697,19 +3730,19 @@ namespace OpenSim.Region.Environment.Scenes
}
}
public bool pipeEventsForScript(uint localID)
public bool PipeEventsForScript(uint localID)
{
SceneObjectPart part = GetSceneObjectPart(localID);
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.
// -- Leaf, Tue Aug 12 14:17:05 EDT 2008
SceneObjectPart parent = part.ParentGroup.RootPart;
if (parent != null && parent.IsAttachment)
return scriptDanger(parent, parent.GetWorldPosition());
return ScriptDanger(parent, parent.GetWorldPosition());
else
return scriptDanger(part, part.GetWorldPosition());
return ScriptDanger(part, part.GetWorldPosition());
}
else
{

View File

@ -225,5 +225,10 @@ namespace OpenSim.Region.Environment.Scenes
{
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)
{
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');
if (lineEnd != 1)
@ -224,8 +230,13 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
int colon = firstline.IndexOf(':');
if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1)
{
engine = firstline.Substring(2, colon-2);
script = "//" + script.Substring(script.IndexOf(':')+1);
string engineName = firstline.Substring(2, colon-2);
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);
#endif
// 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;
KillCurrentScript = false;

View File

@ -30,6 +30,7 @@ using System.Collections.Generic;
using System.Reflection;
using log4net;
using Nini.Config;
using OpenSim.Region.Interfaces;
using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.ScriptEngine.Interfaces;
@ -43,7 +44,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
/// </summary>
///
[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);
@ -126,8 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
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?
m_Scene.StackModuleInterface<IScriptModule>(this);
}
public void PostInitialise()

View File

@ -5114,7 +5114,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Integer llScriptDanger(LSL_Vector pos)
{
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)
{
return 1;

View File

@ -567,85 +567,89 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
}
else
{
SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
m_LocalID);
// m_Engine.Log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
// m_PrimName, m_ScriptName, data.EventName, m_State);
try
if (m_Engine.World.PipeEventsForScript(m_LocalID) ||
data.EventName == "control") // Don't freeze avies!
{
m_CurrentEvent = data.EventName;
m_EventStart = DateTime.Now;
m_InEvent = true;
SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
m_LocalID);
// 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);
m_InEvent = false;
m_CurrentEvent = String.Empty;
if (m_SaveState)
try
{
// This will be the very first event we deliver
// (state_entry) in defualt state
//
m_CurrentEvent = data.EventName;
m_EventStart = DateTime.Now;
m_InEvent = true;
SaveState(m_Assembly);
m_Script.ExecuteEvent(State, data.EventName, data.Params);
m_SaveState = false;
}
}
catch (Exception e)
{
m_InEvent = false;
m_CurrentEvent = String.Empty;
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_SaveState)
{
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);
}
else
{
m_CurrentResult = null;
if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown))
{
m_CurrentResult=m_Engine.QueueEventHandler(this);
}
else
{
m_CurrentResult = null;
}
}
m_DetectParams = null;
return 0;
}
m_DetectParams = null;
return 0;
try
{
// 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());
}
}
try
else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
{
// 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);
m_InSelfDelete = true;
if (part != null && part.ParentGroup != null)
m_Engine.World.DeleteSceneObject(part.ParentGroup);
}
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 Amib.Threading;
using OpenSim.Framework;
using OpenSim.Region.Interfaces;
using OpenSim.Region.Environment;
using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.Environment.Interfaces;
@ -50,7 +51,7 @@ using OpenSim.Region.ScriptEngine.Interfaces;
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);
@ -213,6 +214,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
//
SetupEngine(m_MinThreads, m_MaxThreads, m_IdleTimeout, m_Prio,
m_MaxScriptQueue, m_StackSize);
m_Scene.StackModuleInterface<IScriptModule>(this);
}
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)
{
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');
if (lineEnd != 1)
@ -340,8 +349,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
int colon = firstline.IndexOf(':');
if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1)
{
engine = firstline.Substring(2, colon-2);
script = "//" + script.Substring(script.IndexOf(':')+1);
string engineName = firstline.Substring(2, colon-2);
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})",
// item.Name, itemID.ToString());
ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
string assembly = "";
try
{
assembly = m_Compiler.PerformScriptCompile(script,
assetID.ToString());
if (presence != null)
presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
}
catch (Exception e)
{
if (presence != null)
presence.ControllingClient.SendAgentAlertMessage("Script saved with errors, check debug window!", false);
try
{
// DISPLAY ERROR INWORLD