diff --git a/OpenSim/Region/ScriptEngine/Common/IScript.cs b/OpenSim/Region/ScriptEngine/Common/IScript.cs index 8d91071e89..d38dc7b5db 100644 --- a/OpenSim/Region/ScriptEngine/Common/IScript.cs +++ b/OpenSim/Region/ScriptEngine/Common/IScript.cs @@ -25,7 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Interfaces; diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs index 927ab2cc50..dc3ae05986 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs @@ -29,7 +29,6 @@ using System; using System.Runtime.Remoting.Lifetime; using System.Threading; using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; using OpenSim.Region.ScriptEngine.Interfaces; diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs deleted file mode 100644 index 8293fae16f..0000000000 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventManager.cs +++ /dev/null @@ -1,479 +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 OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney; -using OpenSim.Region.Environment; -using OpenSim.Region.Interfaces; -using OpenSim.Region; -using OpenSim.Region.Environment.Scenes; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase -{ - /// - /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. - /// - [Serializable] - public class EventManager : iScriptEngineFunctionModule - { - // - // Class is instanced in "ScriptEngine" and Uses "EventQueueManager" that is also instanced in "ScriptEngine". - // This class needs a bit of explaining: - // - // This class it the link between an event inside OpenSim and the corresponding event in a user script being executed. - // - // For example when an user touches an object then the "myScriptEngine.World.EventManager.OnObjectGrab" event is fired inside OpenSim. - // We hook up to this event and queue a touch_start in EventQueueManager with the proper LSL parameters. - // It will then be delivered to the script by EventQueueManager. - // - // You can check debug C# dump of an LSL script if you need to verify what exact parameters are needed. - // - - - private ScriptEngine myScriptEngine; - //public IScriptHost TEMP_OBJECT_ID; - public EventManager(ScriptEngine _ScriptEngine, bool performHookUp) - { - myScriptEngine = _ScriptEngine; - ReadConfig(); - - if (performHookUp) - { - myScriptEngine.World.EventManager.OnRezScript += OnRezScript; - } - } - - public void HookUpEvents() - { - // Hook up to events from OpenSim - // We may not want to do it because someone is controlling us and will deliver events to us - - myScriptEngine.Log.Info("[" + myScriptEngine.ScriptEngineName + "]: Hooking up to server events"); - myScriptEngine.World.EventManager.OnObjectGrab += touch_start; - myScriptEngine.World.EventManager.OnObjectDeGrab += touch_end; - myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript; - myScriptEngine.World.EventManager.OnScriptChangedEvent += changed; - myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target; - myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target; - myScriptEngine.World.EventManager.OnScriptControlEvent += control; - myScriptEngine.World.EventManager.OnScriptColliderStart += collision_start; - myScriptEngine.World.EventManager.OnScriptColliding += collision; - myScriptEngine.World.EventManager.OnScriptCollidingEnd += collision_end; - - // TODO: HOOK ALL EVENTS UP TO SERVER! - IMoneyModule money=myScriptEngine.World.RequestModuleInterface(); - if (money != null) - { - money.OnObjectPaid+=HandleObjectPaid; - } - - } - - public void ReadConfig() - { - } - - private void HandleObjectPaid(UUID objectID, UUID agentID, int amount) - { - SceneObjectPart part=myScriptEngine.World.GetSceneObjectPart(objectID); - if (part != null) - { - money(part.LocalId, agentID, amount); - } - } - - public void changed(uint localID, uint change) - { - // Add to queue for all scripts in localID, Object pass change. - myScriptEngine.PostObjectEvent(localID, new EventParams( - "changed",new object[] { new LSL_Types.LSLInteger(change) }, - new DetectParams[0])); - } - - public void state_entry(uint localID) - { - // Add to queue for all scripts in ObjectID object - myScriptEngine.PostObjectEvent(localID, new EventParams( - "state_entry",new object[] { }, - new DetectParams[0])); - } - - public void touch_start(uint localID, uint originalID, Vector3 offsetPos, - IClientAPI remoteClient) - { - // Add to queue for all scripts in ObjectID object - DetectParams[] det = new DetectParams[1]; - det[0] = new DetectParams(); - det[0].Key = remoteClient.AgentId; - det[0].Populate(myScriptEngine.World); - - if (originalID == 0) - { - SceneObjectPart part = myScriptEngine.World.GetSceneObjectPart(localID); - if (part == null) - return; - - det[0].LinkNum = part.LinkNum; - } - else - { - SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID); - det[0].LinkNum = originalPart.LinkNum; - } - - myScriptEngine.PostObjectEvent(localID, new EventParams( - "touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, - det)); - } - - public void touch(uint localID, uint originalID, Vector3 offsetPos, - IClientAPI remoteClient) - { - // Add to queue for all scripts in ObjectID object - DetectParams[] det = new DetectParams[1]; - det[0] = new DetectParams(); - det[0].Key = remoteClient.AgentId; - det[0].Populate(myScriptEngine.World); - det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, - offsetPos.Y, - offsetPos.Z); - - if (originalID == 0) - { - SceneObjectPart part = myScriptEngine.World.GetSceneObjectPart(localID); - if (part == null) - return; - - det[0].LinkNum = part.LinkNum; - } - else - { - SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID); - det[0].LinkNum = originalPart.LinkNum; - } - - myScriptEngine.PostObjectEvent(localID, new EventParams( - "touch", new Object[] { new LSL_Types.LSLInteger(1) }, - det)); - } - - public void touch_end(uint localID, uint originalID, IClientAPI remoteClient) - { - // Add to queue for all scripts in ObjectID object - DetectParams[] det = new DetectParams[1]; - det[0] = new DetectParams(); - det[0].Key = remoteClient.AgentId; - det[0].Populate(myScriptEngine.World); - - if (originalID == 0) - { - SceneObjectPart part = myScriptEngine.World.GetSceneObjectPart(localID); - if (part == null) - return; - - det[0].LinkNum = part.LinkNum; - } - else - { - SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID); - det[0].LinkNum = originalPart.LinkNum; - } - - myScriptEngine.PostObjectEvent(localID, new EventParams( - "touch_end", new Object[] { new LSL_Types.LSLInteger(1) }, - det)); - } - - 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) - { - string firstline = script.Substring(0, lineEnd).Trim(); - - int colon = firstline.IndexOf(':'); - if (firstline.Length > 2 && firstline.Substring(0, 2) == "//" && colon != -1) - { - string engineName = firstline.Substring(2, colon-2); - - if (names.Contains(engineName)) - { - engine = engineName; - script = "//" + script.Substring(script.IndexOf(':')+1); - } - } - } - - if (engine != myScriptEngine.ScriptEngineName) - return; - - myScriptEngine.Log.Debug("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " + - script.Length); - myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script, startParam, postOnRez); - } - - public void OnRemoveScript(uint localID, UUID itemID) - { - myScriptEngine.Log.Debug("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString()); - myScriptEngine.m_ScriptManager.StopScript( - localID, - itemID - ); - } - - public void money(uint localID, UUID agentID, int amount) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "money", new object[] { - new LSL_Types.LSLString(agentID.ToString()), - new LSL_Types.LSLInteger(amount) }, - new DetectParams[0])); - } - - // TODO: Replace placeholders below - // NOTE! THE PARAMETERS FOR THESE FUNCTIONS ARE NOT CORRECT! - // These needs to be hooked up to OpenSim during init of this class - // then queued in EventQueueManager. - // When queued in EventQueueManager they need to be LSL compatible (name and params) - - public void state_exit(uint localID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "state_exit", new object[] { }, - new DetectParams[0])); - } - - public void collision_start(uint localID, ColliderArgs col) - { - // Add to queue for all scripts in ObjectID object - List det = new List(); - - foreach (DetectedObject detobj in col.Colliders) - { - DetectParams d = new DetectParams(); - d.Key =detobj.keyUUID; - d.Populate(myScriptEngine.World); - det.Add(d); - } - - if (det.Count > 0) - myScriptEngine.PostObjectEvent(localID, new EventParams( - "collision_start", - new Object[] { new LSL_Types.LSLInteger(det.Count) }, - det.ToArray())); - } - - public void collision(uint localID, ColliderArgs col) - { - // Add to queue for all scripts in ObjectID object - List det = new List(); - - foreach (DetectedObject detobj in col.Colliders) - { - DetectParams d = new DetectParams(); - d.Key =detobj.keyUUID; - d.Populate(myScriptEngine.World); - det.Add(d); - } - - if (det.Count > 0) - myScriptEngine.PostObjectEvent(localID, new EventParams( - "collision", new Object[] { new LSL_Types.LSLInteger(det.Count) }, - det.ToArray())); - } - - public void collision_end(uint localID, ColliderArgs col) - { - // Add to queue for all scripts in ObjectID object - List det = new List(); - - foreach (DetectedObject detobj in col.Colliders) - { - DetectParams d = new DetectParams(); - d.Key =detobj.keyUUID; - d.Populate(myScriptEngine.World); - det.Add(d); - } - - if (det.Count > 0) - myScriptEngine.PostObjectEvent(localID, new EventParams( - "collision_end", - new Object[] { new LSL_Types.LSLInteger(det.Count) }, - det.ToArray())); - } - - public void land_collision_start(uint localID, UUID itemID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "land_collision_start", - new object[0], - new DetectParams[0])); - } - - public void land_collision(uint localID, UUID itemID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "land_collision", - new object[0], - new DetectParams[0])); - } - - public void land_collision_end(uint localID, UUID itemID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "land_collision_end", - new object[0], - new DetectParams[0])); - } - - // Handled by long commands - public void timer(uint localID, UUID itemID) - { - } - - public void listen(uint localID, UUID itemID) - { - } - - public void control(uint localID, UUID itemID, UUID agentID, uint held, uint change) - { - if ((change == 0) && (myScriptEngine.m_EventQueueManager.CheckEeventQueueForEvent(localID,"control"))) return; - myScriptEngine.PostObjectEvent(localID, new EventParams( - "control",new object[] { - new LSL_Types.LSLString(agentID.ToString()), - new LSL_Types.LSLInteger(held), - new LSL_Types.LSLInteger(change)}, - new DetectParams[0])); - } - - public void email(uint localID, UUID itemID, string timeSent, - string address, string subject, string message, int numLeft) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "email",new object[] { - new LSL_Types.LSLString(timeSent), - new LSL_Types.LSLString(address), - new LSL_Types.LSLString(subject), - new LSL_Types.LSLString(message), - new LSL_Types.LSLInteger(numLeft)}, - new DetectParams[0])); - } - - public void at_target(uint localID, uint handle, Vector3 targetpos, - Vector3 atpos) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "at_target", new object[] { - new LSL_Types.LSLInteger(handle), - new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), - new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, - new DetectParams[0])); - } - - public void not_at_target(uint localID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "not_at_target",new object[0], - new DetectParams[0])); - } - - public void at_rot_target(uint localID, UUID itemID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "at_rot_target",new object[0], - new DetectParams[0])); - } - - public void not_at_rot_target(uint localID, UUID itemID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "not_at_rot_target",new object[0], - new DetectParams[0])); - } - - public void attach(uint localID, UUID itemID) - { - } - - public void dataserver(uint localID, UUID itemID) - { - } - - public void link_message(uint localID, UUID itemID) - { - } - - public void moving_start(uint localID, UUID itemID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "moving_start",new object[0], - new DetectParams[0])); - } - - public void moving_end(uint localID, UUID itemID) - { - myScriptEngine.PostObjectEvent(localID, new EventParams( - "moving_end",new object[0], - new DetectParams[0])); - } - - public void object_rez(uint localID, UUID itemID) - { - } - - public void remote_data(uint localID, UUID itemID) - { - } - - // Handled by long commands - public void http_response(uint localID, UUID itemID) - { - } - - /// - /// If set to true then threads and stuff should try to make a graceful exit - /// - public bool PleaseShutdown - { - get { return _PleaseShutdown; } - set { _PleaseShutdown = value; } - } - private bool _PleaseShutdown = false; - } -} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs deleted file mode 100644 index f259ec1ac9..0000000000 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs +++ /dev/null @@ -1,317 +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.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; -using OpenMetaverse; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase -{ - /// - /// This is the root object for ScriptEngine. Objects access each other trough this class. - /// - /// - [Serializable] - public abstract class ScriptEngine : IRegionModule, IScriptModule, iScriptEngineFunctionModule, IEventReceiver - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public static List ScriptEngines = new List(); - private Scene m_Scene; - public Scene World - { - get { return m_Scene; } - } - 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 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; } - private bool m_enabled = false; - private bool m_hookUpToServer = false; - - public IConfig Config - { - get { return ScriptConfigSource; } - } - - /// - /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. - /// - 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 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) - { - m_Scene = Sceneworld; - ConfigSource = config; - m_hookUpToServer = HookUpToServer; - - m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing"); - - // Make sure we have config - if (ConfigSource.Configs[ScriptEngineName] == null) - ConfigSource.AddConfig(ScriptEngineName); - ScriptConfigSource = ConfigSource.Configs[ScriptEngineName]; - - m_enabled = ScriptConfigSource.GetBoolean("Enabled", true); - if (!m_enabled) - return; - - //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 - m_ScriptManager = newScriptManager; - m_ScriptManager.Setup(); - m_AppDomainManager = new AppDomainManager(this); - if (m_MaintenanceThread == null) - m_MaintenanceThread = new MaintenanceThread(); - - m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\""); - ReadConfig(); - - m_Scene.StackModuleInterface(this); - } - - public void PostInitialise() - { - if (!m_enabled) - return; - - if (m_hookUpToServer) - m_EventManager.HookUpEvents(); - - m_ScriptManager.Start(); - } - - public void Shutdown() - { - // We are shutting down - lock (ScriptEngines) - { - ScriptEngines.Remove(this); - } - } - - 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_MaintenanceThread != null) m_MaintenanceThread.ReadConfig(); - } - - #region IRegionModule - - public abstract void Initialise(Scene scene, IConfigSource config); - - public void Close() - { - } - - public string Name - { - get { return "Common." + ScriptEngineName; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public bool PostObjectEvent(uint localID, EventParams p) - { - return m_EventQueueManager.AddToObjectQueue(localID, p.EventName, p.DetectParams, p.Params); - } - - public bool PostScriptEvent(UUID itemID, EventParams p) - { - uint localID = m_ScriptManager.GetLocalID(itemID); - return m_EventQueueManager.AddToScriptQueue(localID, itemID, p.EventName, p.DetectParams, p.Params); - } - - public DetectParams GetDetectParams(UUID itemID, int number) - { - uint localID = m_ScriptManager.GetLocalID(itemID); - if (localID == 0) - return null; - - IScript Script = m_ScriptManager.GetScript(localID, itemID); - - if (Script == null) - return null; - - DetectParams[] det = m_ScriptManager.GetDetectParams(Script); - - if (number < 0 || number >= det.Length) - return null; - - return det[number]; - } - - public int GetStartParameter(UUID itemID) - { - return 0; - } - #endregion - - public void SetState(UUID itemID, string state) - { - uint localID = m_ScriptManager.GetLocalID(itemID); - if (localID == 0) - return; - - IScript Script = m_ScriptManager.GetScript(localID, itemID); - - if (Script == null) - return; - - string currentState = Script.State; - - if (currentState != state) - { - try - { - m_EventManager.state_exit(localID); - - } - catch (AppDomainUnloadedException) - { - Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance"); - } - - Script.State = state; - - try - { - int eventFlags = m_ScriptManager.GetStateEventFlags(localID, itemID); - SceneObjectPart part = m_Scene.GetSceneObjectPart(itemID); - if (part != null) - part.SetScriptEvents(itemID, eventFlags); - m_EventManager.state_entry(localID); - } - catch (AppDomainUnloadedException) - { - Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance"); - } - } - } - - public bool GetScriptState(UUID itemID) - { - uint localID = m_ScriptManager.GetLocalID(itemID); - if (localID == 0) - return false; - - IScript script = m_ScriptManager.GetScript(localID, itemID); - if (script == null) - return false; - - return script.Exec.Running?true:false; - } - - public void SetScriptState(UUID itemID, bool state) - { - uint localID = m_ScriptManager.GetLocalID(itemID); - if (localID == 0) - return; - - IScript script = m_ScriptManager.GetScript(localID, itemID); - if (script == null) - return; - - script.Exec.Running = state; - } - - public void ApiResetScript(UUID itemID) - { - uint localID = m_ScriptManager.GetLocalID(itemID); - if (localID == 0) - return; - - m_ScriptManager.ResetScript(localID, itemID); - } - - public void ResetScript(UUID itemID) - { - uint localID = m_ScriptManager.GetLocalID(itemID); - if (localID == 0) - return; - - m_ScriptManager.ResetScript(localID, itemID); - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs deleted file mode 100644 index 987a0a0f05..0000000000 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs +++ /dev/null @@ -1,510 +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.IO; -using System.Reflection; -using System.Runtime.Serialization.Formatters.Binary; -using System.Threading; -using OpenMetaverse; -using OpenSim.Region.Environment.Scenes; -using OpenSim.Region.ScriptEngine.Shared; - -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase -{ - /// - /// Loads scripts - /// Compiles them if necessary - /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution) - /// - /// - - // 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 LUQueue = new Queue(); - private static bool PrivateThread; - private int LoadUnloadMaxQueueSize; - private Object scriptLock = new Object(); - private bool m_started = false; - private Dictionary detparms = new Dictionary(); - - // Load/Unload structure - private struct LUStruct - { - public uint localID; - public UUID itemID; - public string script; - public LUType Action; - public int startParam; - public bool postOnRez; - } - - private enum LUType - { - Unknown = 0, - Load = 1, - Unload = 2 - } - - // Xantor 20080525: Keep a list of compiled scripts this session for reuse - public Dictionary scriptList = new Dictionary(); - - // Object> - // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. - // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! - public Dictionary> Scripts = - new Dictionary>(); - - - 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 ScriptEngine m_scriptEngine; - - public ScriptManager(ScriptEngine scriptEngine) - { - m_scriptEngine = scriptEngine; - } - public abstract void Initialize(); - public void Setup() - { - ReadConfig(); - Initialize(); - } - public void Start() - { - m_started = true; - - - 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; - } - } - -// TODO: unused -// 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) - -// TODO: unused -// 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 (!m_started) - return; - - lock (LUQueue) - { - if (LUQueue.Count > 0) - { -m_scriptEngine.Log.InfoFormat("[{0}]: Loading script", m_scriptEngine.ScriptEngineName); - LUStruct item = LUQueue.Dequeue(); - - if (item.Action == LUType.Unload) - { - _StopScript(item.localID, item.itemID); - RemoveScript(item.localID, item.itemID); - } - else if (item.Action == LUType.Load) - { - _StartScript(item.localID, item.itemID, item.script, item.startParam, item.postOnRez); - } - } - } - } - - #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(); - - /// - /// Fetches, loads and hooks up a script to an objects events - /// - /// - /// - public void StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez) - { - lock (LUQueue) - { - if ((LUQueue.Count >= LoadUnloadMaxQueueSize) && m_started) - { - 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; - ls.startParam = startParam; - ls.postOnRez = postOnRez; - LUQueue.Enqueue(ls); -m_scriptEngine.Log.InfoFormat("[{0}]: Queued script for load", m_scriptEngine.ScriptEngineName); - } - } - - /// - /// Disables and unloads a script - /// - /// - /// - public void StopScript(uint localID, UUID itemID) - { - LUStruct ls = new LUStruct(); - ls.localID = localID; - ls.itemID = itemID; - ls.Action = LUType.Unload; - ls.startParam = 0; - ls.postOnRez = false; - lock (LUQueue) - { - 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, UUID itemID, string Script, int startParam, bool postOnRez); - public abstract void _StopScript(uint localID, UUID itemID); - - - #endregion - - #region Perform event execution in script - - /// - /// Execute a LL-event-function in Script - /// - /// Object the script is located in - /// Script ID - /// Name of function - /// Arguments to pass to function - internal void ExecuteEvent(uint localID, UUID itemID, string FunctionName, DetectParams[] 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 - detparms[Script] = qParams; - Script.Exec.ExecuteEvent(FunctionName, args); - detparms.Remove(Script); - } - - public uint GetLocalID(UUID itemID) - { - foreach (KeyValuePair > k in Scripts) - { - if (k.Value.ContainsKey(itemID)) - return k.Key; - } - return 0; - } - - public int GetStateEventFlags(uint localID, UUID itemID) - { - // Console.WriteLine("GetStateEventFlags for <" + localID + "," + itemID + ">"); - try - { - IScript Script = GetScript(localID, itemID); - if (Script == null) - { - return 0; - } - ExecutorBase.scriptEvents evflags = Script.Exec.GetStateEventFlags(); - return (int)evflags; - } - catch (Exception) - { - } - - return 0; - } - - - #endregion - - #region Internal functions to keep track of script - - public List GetScriptKeys(uint localID) - { - if (Scripts.ContainsKey(localID) == false) - return new List(); - - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - - return new List(Obj.Keys); - } - - public IScript GetScript(uint localID, UUID itemID) - { - lock (scriptLock) - { - IScript Script = null; - - if (Scripts.ContainsKey(localID) == false) - return null; - - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - if (Obj.ContainsKey(itemID) == false) - return null; - - // Get script - Obj.TryGetValue(itemID, out Script); - return Script; - } - } - - public void SetScript(uint localID, UUID itemID, IScript Script) - { - lock (scriptLock) - { - // Create object if it doesn't exist - if (Scripts.ContainsKey(localID) == false) - { - Scripts.Add(localID, new Dictionary()); - } - - // Delete script if it exists - Dictionary 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, UUID itemID) - { - if (localID == 0) - localID = GetLocalID(itemID); - - // Don't have that object? - if (Scripts.ContainsKey(localID) == false) - return; - - // Delete script if it exists - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - if (Obj.ContainsKey(itemID) == true) - Obj.Remove(itemID); - } - - #endregion - - - public void ResetScript(uint localID, UUID itemID) - { - IScript s = GetScript(localID, itemID); - string script = s.Source; - StopScript(localID, itemID); - SceneObjectPart part = World.GetSceneObjectPart(localID); - part.GetInventoryItem(itemID).PermsMask = 0; - part.GetInventoryItem(itemID).PermsGranter = UUID.Zero; - StartScript(localID, itemID, script, s.StartParam, false); - } - - - #region Script serialization/deserialization - - public void GetSerializedScript(uint localID, UUID 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, UUID itemID) - { - // Deserialize the script and inject it into an AppDomain - - // How to inject into an AppDomain? - } - - #endregion - - ///// - ///// If set to true then threads and stuff should try to make a graceful exit - ///// - //public bool PleaseShutdown - //{ - // get { return _PleaseShutdown; } - // set { _PleaseShutdown = value; } - //} - //private bool _PleaseShutdown = false; - - public DetectParams[] GetDetectParams(IScript script) - { - if (detparms.ContainsKey(script)) - return detparms[script]; - - return null; - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs deleted file mode 100644 index 768ba6d4d4..0000000000 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/iScriptEngineFunctionModule.cs +++ /dev/null @@ -1,35 +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. - */ - -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase -{ - public interface iScriptEngineFunctionModule - { - void ReadConfig(); -// bool PleaseShutdown { get; set; } - } -} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs similarity index 99% rename from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs rename to OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs index 262d75f49e..969a05e18d 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AppDomainManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs @@ -29,8 +29,9 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; +using OpenSim.Region.ScriptEngine.Common; -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +namespace OpenSim.Region.ScriptEngine.DotNetEngine { public class AppDomainManager : iScriptEngineFunctionModule { diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs similarity index 97% rename from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs rename to OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs index d5ec9b44ee..3d9e19b3e4 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/Common.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs @@ -25,7 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +namespace OpenSim.Region.ScriptEngine.DotNetEngine { public static class Common { diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs index b50e8232e0..4cb74faf05 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs @@ -83,8 +83,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL 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) + public ScriptEngine m_scriptEngine; + public Compiler(ScriptEngine scriptEngine) { m_scriptEngine = scriptEngine; ReadConfig(); diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs similarity index 99% rename from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs rename to OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs index b13ab21415..7805d67fed 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs @@ -31,7 +31,7 @@ using System.Collections.Generic; using OpenMetaverse; using OpenSim.Region.ScriptEngine.Shared; -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +namespace OpenSim.Region.ScriptEngine.DotNetEngine { /// /// EventQueueManager handles event queues diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs similarity index 99% rename from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs rename to OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs index 7f52793859..db3f89f6d5 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs @@ -36,7 +36,7 @@ using log4net; using OpenSim.Framework; using OpenSim.Region.Environment.Scenes.Scripting; -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +namespace OpenSim.Region.ScriptEngine.DotNetEngine { /// /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class @@ -103,7 +103,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase break; default: MyThreadPriority = ThreadPriority.BelowNormal; // Default - m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri + + m_ScriptEngine.Log.Error("[ScriptEngine.DotNetEngine]: Unknown priority type \"" + pri + "\" in config file. Defaulting to \"BelowNormal\"."); break; } diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs similarity index 99% rename from OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs rename to OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs index ef87b2ffe4..6c1528fc47 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs @@ -32,7 +32,7 @@ using System.Threading; using log4net; using OpenSim.Framework; -namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase +namespace OpenSim.Region.ScriptEngine.DotNetEngine { /// /// This class does maintenance on script engine. diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs index e785cc0e59..7ec71c274e 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs @@ -26,29 +26,281 @@ */ using System; +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; +using OpenMetaverse; +using OpenSim.Region.ScriptEngine.Shared; +using OpenSim.Region.ScriptEngine.Common; namespace OpenSim.Region.ScriptEngine.DotNetEngine { [Serializable] - public class ScriptEngine : Common.ScriptEngineBase.ScriptEngine + public class ScriptEngine : IRegionModule, IEventReceiver, IScriptModule { - // We need to override a few things for our DotNetEngine - public override void Initialise(Scene scene, IConfigSource config) + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public static List ScriptEngines = new List(); + private Scene m_Scene; + public Scene World { - ConfigSource = config; - InitializeEngine(scene, config, true, GetScriptManager()); + get { return m_Scene; } + } + 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 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; + private bool m_enabled = false; + + public IConfig Config + { + get { return ScriptConfigSource; } } - public override Common.ScriptEngineBase.ScriptManager _GetScriptManager() - { - return new ScriptManager(this); + /// + /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. + /// + public int RefreshConfigFileSeconds { + get { return (int)(RefreshConfigFilens / 10000000); } + set { RefreshConfigFilens = value * 10000000; } } + public long RefreshConfigFilens; - public override string ScriptEngineName + public string ScriptEngineName { get { return "ScriptEngine.DotNetEngine"; } } + + public 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 Initialise(Scene Sceneworld, IConfigSource config) + { + m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing"); + + ConfigSource = config; + m_Scene = Sceneworld; + + // Make sure we have config + if (ConfigSource.Configs[ScriptEngineName] == null) + ConfigSource.AddConfig(ScriptEngineName); + ScriptConfigSource = ConfigSource.Configs[ScriptEngineName]; + + m_enabled = ScriptConfigSource.GetBoolean("Enabled", true); + if (!m_enabled) + return; + + //m_log.Info("[" + ScriptEngineName + "]: InitializeEngine"); + + // Create all objects we'll be using + m_EventQueueManager = new EventQueueManager(this); + m_EventManager = new EventManager(this, true); + // We need to start it + m_ScriptManager = new ScriptManager(this); + m_ScriptManager.Setup(); + m_AppDomainManager = new AppDomainManager(this); + if (m_MaintenanceThread == null) + m_MaintenanceThread = new MaintenanceThread(); + + m_log.Info("[" + ScriptEngineName + "]: Reading configuration from config section \"" + ScriptEngineName + "\""); + ReadConfig(); + + m_Scene.StackModuleInterface(this); + } + + public void PostInitialise() + { + if (!m_enabled) + return; + + m_EventManager.HookUpEvents(); + + m_ScriptManager.Start(); + } + + public void Shutdown() + { + // We are shutting down + lock (ScriptEngines) + { + ScriptEngines.Remove(this); + } + } + + 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_MaintenanceThread != null) m_MaintenanceThread.ReadConfig(); + } + + #region IRegionModule + + public void Close() + { + } + + public string Name + { + get { return "Common." + ScriptEngineName; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public bool PostObjectEvent(uint localID, EventParams p) + { + return m_EventQueueManager.AddToObjectQueue(localID, p.EventName, p.DetectParams, p.Params); + } + + public bool PostScriptEvent(UUID itemID, EventParams p) + { + uint localID = m_ScriptManager.GetLocalID(itemID); + return m_EventQueueManager.AddToScriptQueue(localID, itemID, p.EventName, p.DetectParams, p.Params); + } + + public DetectParams GetDetectParams(UUID itemID, int number) + { + uint localID = m_ScriptManager.GetLocalID(itemID); + if (localID == 0) + return null; + + IScript Script = m_ScriptManager.GetScript(localID, itemID); + + if (Script == null) + return null; + + DetectParams[] det = m_ScriptManager.GetDetectParams(Script); + + if (number < 0 || number >= det.Length) + return null; + + return det[number]; + } + + public int GetStartParameter(UUID itemID) + { + return 0; + } + #endregion + + public void SetState(UUID itemID, string state) + { + uint localID = m_ScriptManager.GetLocalID(itemID); + if (localID == 0) + return; + + IScript Script = m_ScriptManager.GetScript(localID, itemID); + + if (Script == null) + return; + + string currentState = Script.State; + + if (currentState != state) + { + try + { + m_EventManager.state_exit(localID); + + } + catch (AppDomainUnloadedException) + { + Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance"); + } + + Script.State = state; + + try + { + int eventFlags = m_ScriptManager.GetStateEventFlags(localID, itemID); + SceneObjectPart part = m_Scene.GetSceneObjectPart(itemID); + if (part != null) + part.SetScriptEvents(itemID, eventFlags); + m_EventManager.state_entry(localID); + } + catch (AppDomainUnloadedException) + { + Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance"); + } + } + } + + public bool GetScriptState(UUID itemID) + { + uint localID = m_ScriptManager.GetLocalID(itemID); + if (localID == 0) + return false; + + IScript script = m_ScriptManager.GetScript(localID, itemID); + if (script == null) + return false; + + return script.Exec.Running?true:false; + } + + public void SetScriptState(UUID itemID, bool state) + { + uint localID = m_ScriptManager.GetLocalID(itemID); + if (localID == 0) + return; + + IScript script = m_ScriptManager.GetScript(localID, itemID); + if (script == null) + return; + + script.Exec.Running = state; + } + + public void ApiResetScript(UUID itemID) + { + uint localID = m_ScriptManager.GetLocalID(itemID); + if (localID == 0) + return; + + m_ScriptManager.ResetScript(localID, itemID); + } + + public void ResetScript(UUID itemID) + { + uint localID = m_ScriptManager.GetLocalID(itemID); + if (localID == 0) + return; + + m_ScriptManager.ResetScript(localID, itemID); + } } } diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs index 8ff3bfd2b8..12a8fe4327 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs @@ -34,22 +34,66 @@ using OpenSim.Region.Environment.Scenes; using OpenSim.Region.ScriptEngine.Common; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Threading; namespace OpenSim.Region.ScriptEngine.DotNetEngine { - public class ScriptManager : Common.ScriptEngineBase.ScriptManager + public class ScriptManager { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public ScriptManager(Common.ScriptEngineBase.ScriptEngine scriptEngine) - : base(scriptEngine) + #region Declares + + private Thread scriptLoadUnloadThread; + private static Thread staticScriptLoadUnloadThread; + // private int scriptLoadUnloadThread_IdleSleepms; + private Queue LUQueue = new Queue(); + private static bool PrivateThread; + private int LoadUnloadMaxQueueSize; + private Object scriptLock = new Object(); + private bool m_started = false; + private Dictionary detparms = new Dictionary(); + + // Load/Unload structure + private struct LUStruct { - base.m_scriptEngine = scriptEngine; + public uint localID; + public UUID itemID; + public string script; + public LUType Action; + public int startParam; + public bool postOnRez; } + + private enum LUType + { + Unknown = 0, + Load = 1, + Unload = 2 + } + + // Xantor 20080525: Keep a list of compiled scripts this session for reuse + public Dictionary scriptList = new Dictionary(); + + // Object> + // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. + // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! + public Dictionary> Scripts = + new Dictionary>(); + + + public Scene World + { + get { return m_scriptEngine.World; } + } + + #endregion private Compiler.LSL.Compiler LSLCompiler; - public override void Initialize() + public void Initialize() { // Create our compiler LSLCompiler = new Compiler.LSL.Compiler(m_scriptEngine); @@ -62,7 +106,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine // PROVIDE SCRIPT WITH ITS INTERFACE TO OpenSim - public override void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez) + public void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez) { m_log.DebugFormat( "[{0}]: ScriptManager StartScript: localID: {1}, itemID: {2}", @@ -173,7 +217,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine } } - public override void _StopScript(uint localID, UUID itemID) + public void _StopScript(uint localID, UUID itemID) { IScript LSLBC = GetScript(localID, itemID); if (LSLBC == null) @@ -202,5 +246,405 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine ": " + e.ToString()); } } + + 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 ScriptEngine m_scriptEngine; + + public ScriptManager(ScriptEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + } + public void Setup() + { + ReadConfig(); + Initialize(); + } + public void Start() + { + m_started = true; + + + 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; + } + } + +// TODO: unused +// 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) + +// TODO: unused +// 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 (!m_started) + return; + + lock (LUQueue) + { + if (LUQueue.Count > 0) + { +m_scriptEngine.Log.InfoFormat("[{0}]: Loading script", m_scriptEngine.ScriptEngineName); + LUStruct item = LUQueue.Dequeue(); + + if (item.Action == LUType.Unload) + { + _StopScript(item.localID, item.itemID); + RemoveScript(item.localID, item.itemID); + } + else if (item.Action == LUType.Load) + { + _StartScript(item.localID, item.itemID, item.script, item.startParam, item.postOnRez); + } + } + } + } + + #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(); + + /// + /// Fetches, loads and hooks up a script to an objects events + /// + /// + /// + public void StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez) + { + lock (LUQueue) + { + if ((LUQueue.Count >= LoadUnloadMaxQueueSize) && m_started) + { + 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; + ls.startParam = startParam; + ls.postOnRez = postOnRez; + LUQueue.Enqueue(ls); +m_scriptEngine.Log.InfoFormat("[{0}]: Queued script for load", m_scriptEngine.ScriptEngineName); + } + } + + /// + /// Disables and unloads a script + /// + /// + /// + public void StopScript(uint localID, UUID itemID) + { + LUStruct ls = new LUStruct(); + ls.localID = localID; + ls.itemID = itemID; + ls.Action = LUType.Unload; + ls.startParam = 0; + ls.postOnRez = false; + lock (LUQueue) + { + LUQueue.Enqueue(ls); + } + } + + // Create a new instance of the compiler (reuse) + //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler(); + + + #endregion + + #region Perform event execution in script + + /// + /// Execute a LL-event-function in Script + /// + /// Object the script is located in + /// Script ID + /// Name of function + /// Arguments to pass to function + internal void ExecuteEvent(uint localID, UUID itemID, string FunctionName, DetectParams[] 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 + detparms[Script] = qParams; + Script.Exec.ExecuteEvent(FunctionName, args); + detparms.Remove(Script); + } + + public uint GetLocalID(UUID itemID) + { + foreach (KeyValuePair > k in Scripts) + { + if (k.Value.ContainsKey(itemID)) + return k.Key; + } + return 0; + } + + public int GetStateEventFlags(uint localID, UUID itemID) + { + // Console.WriteLine("GetStateEventFlags for <" + localID + "," + itemID + ">"); + try + { + IScript Script = GetScript(localID, itemID); + if (Script == null) + { + return 0; + } + ExecutorBase.scriptEvents evflags = Script.Exec.GetStateEventFlags(); + return (int)evflags; + } + catch (Exception) + { + } + + return 0; + } + + + #endregion + + #region Internal functions to keep track of script + + public List GetScriptKeys(uint localID) + { + if (Scripts.ContainsKey(localID) == false) + return new List(); + + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + + return new List(Obj.Keys); + } + + public IScript GetScript(uint localID, UUID itemID) + { + lock (scriptLock) + { + IScript Script = null; + + if (Scripts.ContainsKey(localID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == false) + return null; + + // Get script + Obj.TryGetValue(itemID, out Script); + return Script; + } + } + + public void SetScript(uint localID, UUID itemID, IScript Script) + { + lock (scriptLock) + { + // Create object if it doesn't exist + if (Scripts.ContainsKey(localID) == false) + { + Scripts.Add(localID, new Dictionary()); + } + + // Delete script if it exists + Dictionary 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, UUID itemID) + { + if (localID == 0) + localID = GetLocalID(itemID); + + // Don't have that object? + if (Scripts.ContainsKey(localID) == false) + return; + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == true) + Obj.Remove(itemID); + } + + #endregion + + + public void ResetScript(uint localID, UUID itemID) + { + IScript s = GetScript(localID, itemID); + string script = s.Source; + StopScript(localID, itemID); + SceneObjectPart part = World.GetSceneObjectPart(localID); + part.GetInventoryItem(itemID).PermsMask = 0; + part.GetInventoryItem(itemID).PermsGranter = UUID.Zero; + StartScript(localID, itemID, script, s.StartParam, false); + } + + + #region Script serialization/deserialization + + public void GetSerializedScript(uint localID, UUID 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, UUID itemID) + { + // Deserialize the script and inject it into an AppDomain + + // How to inject into an AppDomain? + } + + #endregion + + ///// + ///// If set to true then threads and stuff should try to make a graceful exit + ///// + //public bool PleaseShutdown + //{ + // get { return _PleaseShutdown; } + // set { _PleaseShutdown = value; } + //} + //private bool _PleaseShutdown = false; + + public DetectParams[] GetDetectParams(IScript script) + { + if (detparms.ContainsKey(script)) + return detparms[script]; + + return null; + } } }