From f11107821e259d544dc42648f4cdba2b123cd71e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 25 Sep 2008 17:26:32 +0000 Subject: 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 --- OpenSim/Framework/IScene.cs | 1 + .../Region/Environment/Scenes/Scene.Inventory.cs | 6 + OpenSim/Region/Environment/Scenes/Scene.cs | 53 +++++++-- OpenSim/Region/Environment/Scenes/SceneBase.cs | 5 + OpenSim/Region/Interfaces/IScriptModule.cs | 38 +++++++ .../Common/ScriptEngineBase/EventManager.cs | 15 ++- .../ScriptEngineBase/EventQueueThreadClass.cs | 2 +- .../Common/ScriptEngineBase/ScriptEngine.cs | 6 +- .../Shared/Api/Implementation/LSL_Api_Base.cs | 2 +- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 126 +++++++++++---------- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 26 ++++- 11 files changed, 199 insertions(+), 81 deletions(-) create mode 100644 OpenSim/Region/Interfaces/IScriptModule.cs (limited to 'OpenSim') diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index d3e79d0..b6043ac 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs @@ -65,5 +65,6 @@ namespace OpenSim.Framework string GetCapsPath(UUID agentId); T RequestModuleInterface(); + T[] RequestModuleInterfaces(); } } diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs index 2a9be81..8fec13f 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs @@ -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); + } } /// diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 74502b8..e5f10b8 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -124,7 +124,7 @@ namespace OpenSim.Region.Environment.Scenes { get { return m_modules; } } - protected Dictionary ModuleInterfaces = new Dictionary(); + protected Dictionary > ModuleInterfaces = new Dictionary >(); protected Dictionary ModuleAPIMethods = new Dictionary(); protected Dictionary m_moduleCommanders = new Dictionary(); @@ -3025,10 +3025,27 @@ namespace OpenSim.Region.Environment.Scenes { if (!ModuleInterfaces.ContainsKey(typeof(M))) { - ModuleInterfaces.Add(typeof(M), mod); + List l = new List(); + l.Add(mod); + ModuleInterfaces.Add(typeof(M), l); } } + public void StackModuleInterface(M mod) + { + List l; + if (ModuleInterfaces.ContainsKey(typeof(M))) + l = ModuleInterfaces[typeof(M)]; + else + l = new List(); + + if (l.Contains(mod)) + return; + + l.Add(mod); + ModuleInterfaces[typeof(M)] = l; + } + /// /// For the given interface, retrieve the region module which implements it. /// @@ -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() + { + if (ModuleInterfaces.ContainsKey(typeof(T))) + { + List ret = new List(); + + 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 { diff --git a/OpenSim/Region/Environment/Scenes/SceneBase.cs b/OpenSim/Region/Environment/Scenes/SceneBase.cs index 955fd22..1406b47 100644 --- a/OpenSim/Region/Environment/Scenes/SceneBase.cs +++ b/OpenSim/Region/Environment/Scenes/SceneBase.cs @@ -225,5 +225,10 @@ namespace OpenSim.Region.Environment.Scenes { return default(T); } + + public virtual T[] RequestModuleInterfaces() + { + return new T[] { default(T) }; + } } } diff --git a/OpenSim/Region/Interfaces/IScriptModule.cs b/OpenSim/Region/Interfaces/IScriptModule.cs new file mode 100644 index 0000000..e01b472 --- /dev/null +++ b/OpenSim/Region/Interfaces/IScriptModule.cs @@ -0,0 +1,38 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Region.Interfaces +{ + public interface IScriptModule + { + string ScriptEngineName { get; } + } +} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs index c8c9cd8..0308169 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs @@ -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 engines = new List(myScriptEngine.World.RequestModuleInterfaces()); + + List names = new List(); + 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); + } } } diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs index 1e71ae5..7f52793 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs @@ -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; diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs index d423311..2bcd949 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs @@ -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 /// /// [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(this); } public void PostInitialise() diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs index 320e878..396d924 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs @@ -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; diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 28a3b11..6e6d169 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -567,86 +567,90 @@ 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); + try + { + m_CurrentEvent = data.EventName; + m_EventStart = DateTime.Now; + m_InEvent = true; - m_InEvent = false; - m_CurrentEvent = String.Empty; + m_Script.ExecuteEvent(State, data.EventName, data.Params); - if (m_SaveState) - { - // This will be the very first event we deliver - // (state_entry) in defualt state - // + m_InEvent = false; + m_CurrentEvent = String.Empty; - SaveState(m_Assembly); + if (m_SaveState) + { + // This will be the very first event we deliver + // (state_entry) in defualt state + // - m_SaveState = false; - } - } - catch (Exception e) - { - m_InEvent = false; - m_CurrentEvent = String.Empty; + SaveState(m_Assembly); - if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException)))) + m_SaveState = false; + } + } + catch (Exception e) { - if (e is System.Threading.ThreadAbortException) + m_InEvent = false; + m_CurrentEvent = String.Empty; + + if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException)))) { - lock (m_EventQueue) + 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)) + { + m_CurrentResult=m_Engine.QueueEventHandler(this); + } + else + { + m_CurrentResult = null; + } } - else - { - m_CurrentResult = null; - } - } - m_DetectParams = null; + m_DetectParams = null; - return 0; - } + 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); + 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()); + } } - catch (Exception e2) // LEGIT: User Scripting + else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) { - 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()); + m_InSelfDelete = true; + if (part != null && part.ParentGroup != null) + m_Engine.World.DeleteSceneObject(part.ParentGroup); } } - else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) - { - m_InSelfDelete = true; - if (part != null && part.ParentGroup != null) - m_Engine.World.DeleteSceneObject(part.ParentGroup); - } } } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 701ad60..f11ccc4 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -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(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 engines = new List(m_Scene.RequestModuleInterfaces()); + + List names = new List(); + 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 -- cgit v1.1