Set eol
							parent
							
								
									33d82aa532
								
							
						
					
					
						commit
						0081c060d0
					
				
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,239 +1,239 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using OpenSim.Region.ScriptEngine.Common;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    public class AppDomainManager
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // This class does AppDomain handling and loading/unloading of scripts in it.
 | 
			
		||||
        // It is instanced in "ScriptEngine" and controlled from "ScriptManager"
 | 
			
		||||
        //
 | 
			
		||||
        // 1. Create a new AppDomain if old one is full (or doesn't exist)
 | 
			
		||||
        // 2. Load scripts into AppDomain
 | 
			
		||||
        // 3. Unload scripts from AppDomain (stopping them and marking them as inactive)
 | 
			
		||||
        // 4. Unload AppDomain completely when all scripts in it has stopped
 | 
			
		||||
        //
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private int maxScriptsPerAppDomain = 1;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Internal list of all AppDomains
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Structure to keep track of data around AppDomain
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private class AppDomainStructure
 | 
			
		||||
        {
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// The AppDomain itself
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            public AppDomain CurrentAppDomain;
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Number of scripts loaded into AppDomain
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            public int ScriptsLoaded;
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Number of dead scripts
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            public int ScriptsWaitingUnload;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Current AppDomain
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private AppDomainStructure currentAD;
 | 
			
		||||
 | 
			
		||||
        private object getLock = new object(); // Mutex
 | 
			
		||||
        private object freeLock = new object(); // Mutex
 | 
			
		||||
 | 
			
		||||
        //private ScriptEngine m_scriptEngine;
 | 
			
		||||
        //public AppDomainManager(ScriptEngine scriptEngine)
 | 
			
		||||
        public AppDomainManager()
 | 
			
		||||
        {
 | 
			
		||||
            //m_scriptEngine = scriptEngine;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Find a free AppDomain, creating one if necessary
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>Free AppDomain</returns>
 | 
			
		||||
        private AppDomainStructure GetFreeAppDomain()
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("Finding free AppDomain");
 | 
			
		||||
            lock (getLock)
 | 
			
		||||
            {
 | 
			
		||||
                // Current full?
 | 
			
		||||
                if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
 | 
			
		||||
                {
 | 
			
		||||
                    // Add it to AppDomains list and empty current
 | 
			
		||||
                    appDomains.Add(currentAD);
 | 
			
		||||
                    currentAD = null;
 | 
			
		||||
                }
 | 
			
		||||
                // No current
 | 
			
		||||
                if (currentAD == null)
 | 
			
		||||
                {
 | 
			
		||||
                    // Create a new current AppDomain
 | 
			
		||||
                    currentAD = new AppDomainStructure();
 | 
			
		||||
                    currentAD.CurrentAppDomain = PrepareNewAppDomain();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
 | 
			
		||||
                return currentAD;
 | 
			
		||||
            } // lock
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private int AppDomainNameCount;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create and prepare a new AppDomain for scripts
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The new AppDomain</returns>
 | 
			
		||||
        private AppDomain PrepareNewAppDomain()
 | 
			
		||||
        {
 | 
			
		||||
            // Create and prepare a new AppDomain
 | 
			
		||||
            AppDomainNameCount++;
 | 
			
		||||
            // TODO: Currently security match current appdomain
 | 
			
		||||
 | 
			
		||||
            // Construct and initialize settings for a second AppDomain.
 | 
			
		||||
            AppDomainSetup ads = new AppDomainSetup();
 | 
			
		||||
            ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
 | 
			
		||||
            ads.DisallowBindingRedirects = false;
 | 
			
		||||
            ads.DisallowCodeDownload = true;
 | 
			
		||||
            ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;)
 | 
			
		||||
            ads.ShadowCopyFiles = "true"; // Enabled shadowing
 | 
			
		||||
            ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
 | 
			
		||||
 | 
			
		||||
            AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
 | 
			
		||||
            Console.WriteLine("Loading: " +
 | 
			
		||||
                              AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString());
 | 
			
		||||
            AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll"));
 | 
			
		||||
 | 
			
		||||
            // Return the new AppDomain
 | 
			
		||||
            return AD;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Unload appdomains that are full and have only dead scripts
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void UnloadAppDomains()
 | 
			
		||||
        {
 | 
			
		||||
            lock (freeLock)
 | 
			
		||||
            {
 | 
			
		||||
                // Go through all
 | 
			
		||||
                foreach (AppDomainStructure ads in new ArrayList(appDomains))
 | 
			
		||||
                {
 | 
			
		||||
                    // Don't process current AppDomain
 | 
			
		||||
                    if (ads.CurrentAppDomain != currentAD.CurrentAppDomain)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Not current AppDomain
 | 
			
		||||
                        // Is number of unloaded bigger or equal to number of loaded?
 | 
			
		||||
                        if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload)
 | 
			
		||||
                        {
 | 
			
		||||
                            Console.WriteLine("Found empty AppDomain, unloading");
 | 
			
		||||
                            // Remove from internal list
 | 
			
		||||
                            appDomains.Remove(ads);
 | 
			
		||||
#if DEBUG
 | 
			
		||||
                            long m = GC.GetTotalMemory(true);
 | 
			
		||||
#endif
 | 
			
		||||
                            // Unload
 | 
			
		||||
                            AppDomain.Unload(ads.CurrentAppDomain);
 | 
			
		||||
#if DEBUG
 | 
			
		||||
                            Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) +
 | 
			
		||||
                                              " bytes of memory");
 | 
			
		||||
#endif
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } // foreach
 | 
			
		||||
            } // lock
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public IScript LoadScript(string FileName)
 | 
			
		||||
        {
 | 
			
		||||
            // Find next available AppDomain to put it in
 | 
			
		||||
            AppDomainStructure FreeAppDomain = GetFreeAppDomain();
 | 
			
		||||
 | 
			
		||||
            Console.WriteLine("Loading into AppDomain: " + FileName);
 | 
			
		||||
            IScript mbrt =
 | 
			
		||||
                (IScript)
 | 
			
		||||
                FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
 | 
			
		||||
            //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
 | 
			
		||||
            FreeAppDomain.ScriptsLoaded++;
 | 
			
		||||
 | 
			
		||||
            return mbrt;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Increase "dead script" counter for an AppDomain
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="ad"></param>
 | 
			
		||||
        //[Obsolete("Needs fixing, needs a real purpose in life!!!")]
 | 
			
		||||
        public void StopScript(AppDomain ad)
 | 
			
		||||
        {
 | 
			
		||||
            lock (freeLock)
 | 
			
		||||
            {
 | 
			
		||||
                Console.WriteLine("Stopping script in AppDomain");
 | 
			
		||||
                // Check if it is current AppDomain
 | 
			
		||||
                if (currentAD.CurrentAppDomain == ad)
 | 
			
		||||
                {
 | 
			
		||||
                    // Yes - increase
 | 
			
		||||
                    currentAD.ScriptsWaitingUnload++;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Lopp through all AppDomains
 | 
			
		||||
                foreach (AppDomainStructure ads in new ArrayList(appDomains))
 | 
			
		||||
                {
 | 
			
		||||
                    if (ads.CurrentAppDomain == ad)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Found it
 | 
			
		||||
                        ads.ScriptsWaitingUnload++;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                } // foreach
 | 
			
		||||
            } // lock
 | 
			
		||||
 | 
			
		||||
            UnloadAppDomains(); // Outsite lock, has its own GetLock
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using OpenSim.Region.ScriptEngine.Common;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    public class AppDomainManager
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // This class does AppDomain handling and loading/unloading of scripts in it.
 | 
			
		||||
        // It is instanced in "ScriptEngine" and controlled from "ScriptManager"
 | 
			
		||||
        //
 | 
			
		||||
        // 1. Create a new AppDomain if old one is full (or doesn't exist)
 | 
			
		||||
        // 2. Load scripts into AppDomain
 | 
			
		||||
        // 3. Unload scripts from AppDomain (stopping them and marking them as inactive)
 | 
			
		||||
        // 4. Unload AppDomain completely when all scripts in it has stopped
 | 
			
		||||
        //
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private int maxScriptsPerAppDomain = 1;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Internal list of all AppDomains
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private List<AppDomainStructure> appDomains = new List<AppDomainStructure>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Structure to keep track of data around AppDomain
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private class AppDomainStructure
 | 
			
		||||
        {
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// The AppDomain itself
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            public AppDomain CurrentAppDomain;
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Number of scripts loaded into AppDomain
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            public int ScriptsLoaded;
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Number of dead scripts
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            public int ScriptsWaitingUnload;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Current AppDomain
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private AppDomainStructure currentAD;
 | 
			
		||||
 | 
			
		||||
        private object getLock = new object(); // Mutex
 | 
			
		||||
        private object freeLock = new object(); // Mutex
 | 
			
		||||
 | 
			
		||||
        //private ScriptEngine m_scriptEngine;
 | 
			
		||||
        //public AppDomainManager(ScriptEngine scriptEngine)
 | 
			
		||||
        public AppDomainManager()
 | 
			
		||||
        {
 | 
			
		||||
            //m_scriptEngine = scriptEngine;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Find a free AppDomain, creating one if necessary
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>Free AppDomain</returns>
 | 
			
		||||
        private AppDomainStructure GetFreeAppDomain()
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("Finding free AppDomain");
 | 
			
		||||
            lock (getLock)
 | 
			
		||||
            {
 | 
			
		||||
                // Current full?
 | 
			
		||||
                if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain)
 | 
			
		||||
                {
 | 
			
		||||
                    // Add it to AppDomains list and empty current
 | 
			
		||||
                    appDomains.Add(currentAD);
 | 
			
		||||
                    currentAD = null;
 | 
			
		||||
                }
 | 
			
		||||
                // No current
 | 
			
		||||
                if (currentAD == null)
 | 
			
		||||
                {
 | 
			
		||||
                    // Create a new current AppDomain
 | 
			
		||||
                    currentAD = new AppDomainStructure();
 | 
			
		||||
                    currentAD.CurrentAppDomain = PrepareNewAppDomain();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded);
 | 
			
		||||
                return currentAD;
 | 
			
		||||
            } // lock
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private int AppDomainNameCount;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create and prepare a new AppDomain for scripts
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The new AppDomain</returns>
 | 
			
		||||
        private AppDomain PrepareNewAppDomain()
 | 
			
		||||
        {
 | 
			
		||||
            // Create and prepare a new AppDomain
 | 
			
		||||
            AppDomainNameCount++;
 | 
			
		||||
            // TODO: Currently security match current appdomain
 | 
			
		||||
 | 
			
		||||
            // Construct and initialize settings for a second AppDomain.
 | 
			
		||||
            AppDomainSetup ads = new AppDomainSetup();
 | 
			
		||||
            ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
 | 
			
		||||
            ads.DisallowBindingRedirects = false;
 | 
			
		||||
            ads.DisallowCodeDownload = true;
 | 
			
		||||
            ads.LoaderOptimization = LoaderOptimization.MultiDomain; // Sounds good ;)
 | 
			
		||||
            ads.ShadowCopyFiles = "true"; // Enabled shadowing
 | 
			
		||||
            ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
 | 
			
		||||
 | 
			
		||||
            AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads);
 | 
			
		||||
            Console.WriteLine("Loading: " +
 | 
			
		||||
                              AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll").ToString());
 | 
			
		||||
            AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Common.dll"));
 | 
			
		||||
 | 
			
		||||
            // Return the new AppDomain
 | 
			
		||||
            return AD;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Unload appdomains that are full and have only dead scripts
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void UnloadAppDomains()
 | 
			
		||||
        {
 | 
			
		||||
            lock (freeLock)
 | 
			
		||||
            {
 | 
			
		||||
                // Go through all
 | 
			
		||||
                foreach (AppDomainStructure ads in new ArrayList(appDomains))
 | 
			
		||||
                {
 | 
			
		||||
                    // Don't process current AppDomain
 | 
			
		||||
                    if (ads.CurrentAppDomain != currentAD.CurrentAppDomain)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Not current AppDomain
 | 
			
		||||
                        // Is number of unloaded bigger or equal to number of loaded?
 | 
			
		||||
                        if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload)
 | 
			
		||||
                        {
 | 
			
		||||
                            Console.WriteLine("Found empty AppDomain, unloading");
 | 
			
		||||
                            // Remove from internal list
 | 
			
		||||
                            appDomains.Remove(ads);
 | 
			
		||||
#if DEBUG
 | 
			
		||||
                            long m = GC.GetTotalMemory(true);
 | 
			
		||||
#endif
 | 
			
		||||
                            // Unload
 | 
			
		||||
                            AppDomain.Unload(ads.CurrentAppDomain);
 | 
			
		||||
#if DEBUG
 | 
			
		||||
                            Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) +
 | 
			
		||||
                                              " bytes of memory");
 | 
			
		||||
#endif
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } // foreach
 | 
			
		||||
            } // lock
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public IScript LoadScript(string FileName)
 | 
			
		||||
        {
 | 
			
		||||
            // Find next available AppDomain to put it in
 | 
			
		||||
            AppDomainStructure FreeAppDomain = GetFreeAppDomain();
 | 
			
		||||
 | 
			
		||||
            Console.WriteLine("Loading into AppDomain: " + FileName);
 | 
			
		||||
            IScript mbrt =
 | 
			
		||||
                (IScript)
 | 
			
		||||
                FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script");
 | 
			
		||||
            //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
 | 
			
		||||
            FreeAppDomain.ScriptsLoaded++;
 | 
			
		||||
 | 
			
		||||
            return mbrt;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Increase "dead script" counter for an AppDomain
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="ad"></param>
 | 
			
		||||
        //[Obsolete("Needs fixing, needs a real purpose in life!!!")]
 | 
			
		||||
        public void StopScript(AppDomain ad)
 | 
			
		||||
        {
 | 
			
		||||
            lock (freeLock)
 | 
			
		||||
            {
 | 
			
		||||
                Console.WriteLine("Stopping script in AppDomain");
 | 
			
		||||
                // Check if it is current AppDomain
 | 
			
		||||
                if (currentAD.CurrentAppDomain == ad)
 | 
			
		||||
                {
 | 
			
		||||
                    // Yes - increase
 | 
			
		||||
                    currentAD.ScriptsWaitingUnload++;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Lopp through all AppDomains
 | 
			
		||||
                foreach (AppDomainStructure ads in new ArrayList(appDomains))
 | 
			
		||||
                {
 | 
			
		||||
                    if (ads.CurrentAppDomain == ad)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Found it
 | 
			
		||||
                        ads.ScriptsWaitingUnload++;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                } // foreach
 | 
			
		||||
            } // lock
 | 
			
		||||
 | 
			
		||||
            UnloadAppDomains(); // Outsite lock, has its own GetLock
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,58 +1,58 @@
 | 
			
		|||
/*
 | 
			
		||||
* 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 static class Common
 | 
			
		||||
    {
 | 
			
		||||
        public static bool debug = true;
 | 
			
		||||
        public static ScriptEngine mySE;
 | 
			
		||||
 | 
			
		||||
        // This class just contains some static log stuff used for debugging.
 | 
			
		||||
 | 
			
		||||
        //public delegate void SendToDebugEventDelegate(string Message);
 | 
			
		||||
        //public delegate void SendToLogEventDelegate(string Message);
 | 
			
		||||
        //static public event SendToDebugEventDelegate SendToDebugEvent;
 | 
			
		||||
        //static public event SendToLogEventDelegate SendToLogEvent;
 | 
			
		||||
 | 
			
		||||
        public static void SendToDebug(string Message)
 | 
			
		||||
        {
 | 
			
		||||
            //if (Debug == true)
 | 
			
		||||
            mySE.Log.Verbose("ScriptEngine", "Debug: " + Message);
 | 
			
		||||
            //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SendToLog(string Message)
 | 
			
		||||
        {
 | 
			
		||||
            //if (Debug == true)
 | 
			
		||||
            mySE.Log.Verbose("ScriptEngine", "LOG: " + Message);
 | 
			
		||||
            //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
/*
 | 
			
		||||
* 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 static class Common
 | 
			
		||||
    {
 | 
			
		||||
        public static bool debug = true;
 | 
			
		||||
        public static ScriptEngine mySE;
 | 
			
		||||
 | 
			
		||||
        // This class just contains some static log stuff used for debugging.
 | 
			
		||||
 | 
			
		||||
        //public delegate void SendToDebugEventDelegate(string Message);
 | 
			
		||||
        //public delegate void SendToLogEventDelegate(string Message);
 | 
			
		||||
        //static public event SendToDebugEventDelegate SendToDebugEvent;
 | 
			
		||||
        //static public event SendToLogEventDelegate SendToLogEvent;
 | 
			
		||||
 | 
			
		||||
        public static void SendToDebug(string Message)
 | 
			
		||||
        {
 | 
			
		||||
            //if (Debug == true)
 | 
			
		||||
            mySE.Log.Verbose("ScriptEngine", "Debug: " + Message);
 | 
			
		||||
            //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SendToLog(string Message)
 | 
			
		||||
        {
 | 
			
		||||
            //if (Debug == true)
 | 
			
		||||
            mySE.Log.Verbose("ScriptEngine", "LOG: " + Message);
 | 
			
		||||
            //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,260 +1,260 @@
 | 
			
		|||
/*
 | 
			
		||||
* 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 libsecondlife;
 | 
			
		||||
using OpenSim.Framework;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // 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;
 | 
			
		||||
 | 
			
		||||
            // Hook up to events from OpenSim
 | 
			
		||||
            // We may not want to do it because someone is controlling us and will deliver events to us
 | 
			
		||||
            if (performHookUp)
 | 
			
		||||
            {
 | 
			
		||||
                myScriptEngine.Log.Verbose("ScriptEngine", "Hooking up to server events");
 | 
			
		||||
                myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
 | 
			
		||||
                myScriptEngine.World.EventManager.OnRezScript += OnRezScript;
 | 
			
		||||
                myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript;
 | 
			
		||||
                // TODO: HOOK ALL EVENTS UP TO SERVER!
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient)
 | 
			
		||||
        {
 | 
			
		||||
            // Add to queue for all scripts in ObjectID object
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] {(int) 1});
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnRezScript(uint localID, LLUUID itemID, string script)
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " +
 | 
			
		||||
                              script.Length);
 | 
			
		||||
            myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnRemoveScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString());
 | 
			
		||||
            myScriptEngine.m_ScriptManager.StopScript(
 | 
			
		||||
                localID,
 | 
			
		||||
                itemID
 | 
			
		||||
                );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_exit");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void touch(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void touch_end(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch_end");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void collision_start(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_start");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void collision(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void collision_end(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_end");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void land_collision_start(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_start");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void land_collision(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void land_collision_end(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_end");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Handled by long commands
 | 
			
		||||
        public void timer(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            //myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void listen(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "listen");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void on_rez(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "on_rez");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void sensor(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "sensor");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void no_sensor(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "no_sensor");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void control(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "control");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void money(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "money");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void email(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "email");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void at_target(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_target");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void not_at_target(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_target");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void at_rot_target(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_rot_target");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void not_at_rot_target(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_rot_target");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void run_time_permissions(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "run_time_permissions");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void changed(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "changed");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void attach(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "attach");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void dataserver(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "dataserver");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void link_message(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "link_message");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void moving_start(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_start");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void moving_end(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_end");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void object_rez(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "object_rez");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void remote_data(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "remote_data");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Handled by long commands
 | 
			
		||||
        public void http_response(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            //    myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "http_response");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
/*
 | 
			
		||||
* 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 libsecondlife;
 | 
			
		||||
using OpenSim.Framework;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public class EventManager : OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.RemoteEvents
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // 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;
 | 
			
		||||
 | 
			
		||||
            // Hook up to events from OpenSim
 | 
			
		||||
            // We may not want to do it because someone is controlling us and will deliver events to us
 | 
			
		||||
            if (performHookUp)
 | 
			
		||||
            {
 | 
			
		||||
                myScriptEngine.Log.Verbose("ScriptEngine", "Hooking up to server events");
 | 
			
		||||
                myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
 | 
			
		||||
                myScriptEngine.World.EventManager.OnRezScript += OnRezScript;
 | 
			
		||||
                myScriptEngine.World.EventManager.OnRemoveScript += OnRemoveScript;
 | 
			
		||||
                // TODO: HOOK ALL EVENTS UP TO SERVER!
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient)
 | 
			
		||||
        {
 | 
			
		||||
            // Add to queue for all scripts in ObjectID object
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] {(int) 1});
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnRezScript(uint localID, LLUUID itemID, string script)
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("OnRezScript localID: " + localID + " LLUID: " + itemID.ToString() + " Size: " +
 | 
			
		||||
                              script.Length);
 | 
			
		||||
            myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void OnRemoveScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString());
 | 
			
		||||
            myScriptEngine.m_ScriptManager.StopScript(
 | 
			
		||||
                localID,
 | 
			
		||||
                itemID
 | 
			
		||||
                );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "state_exit");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void touch(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void touch_end(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "touch_end");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void collision_start(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_start");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void collision(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void collision_end(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "collision_end");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void land_collision_start(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_start");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void land_collision(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void land_collision_end(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "land_collision_end");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Handled by long commands
 | 
			
		||||
        public void timer(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            //myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void listen(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "listen");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void on_rez(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "on_rez");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void sensor(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "sensor");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void no_sensor(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "no_sensor");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void control(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "control");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void money(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "money");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void email(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "email");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void at_target(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_target");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void not_at_target(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_target");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void at_rot_target(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "at_rot_target");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void not_at_rot_target(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "not_at_rot_target");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void run_time_permissions(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "run_time_permissions");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void changed(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "changed");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void attach(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "attach");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void dataserver(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "dataserver");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void link_message(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "link_message");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void moving_start(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_start");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void moving_end(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "moving_end");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void object_rez(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "object_rez");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void remote_data(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "remote_data");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Handled by long commands
 | 
			
		||||
        public void http_response(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            //    myScriptEngine.m_EventQueueManager.AddToScriptQueue(localID, itemID, "http_response");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,364 +1,364 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using libsecondlife;
 | 
			
		||||
using OpenSim.Framework;
 | 
			
		||||
using OpenSim.Region.Environment.Scenes.Scripting;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// EventQueueManager handles event queues
 | 
			
		||||
    /// Events are queued and executed in separate thread
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public class EventQueueManager
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine".
 | 
			
		||||
        //
 | 
			
		||||
        // Class purpose is to queue and execute functions that are received by "EventManager":
 | 
			
		||||
        //   - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution.
 | 
			
		||||
        //   - allowing us to prioritize and control execution of script functions.
 | 
			
		||||
        // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety.
 | 
			
		||||
        //
 | 
			
		||||
        // 1. Hold an execution queue for scripts
 | 
			
		||||
        // 2. Use threads to process queue, each thread executes one script function on each pass.
 | 
			
		||||
        // 3. Catch any script error and process it
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        // Notes:
 | 
			
		||||
        // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts.
 | 
			
		||||
        //   Not noticeable unless server is under high load.
 | 
			
		||||
        // * This class contains the number of threads used for script executions. Since we are not microthreading scripts yet,
 | 
			
		||||
        //   increase number of threads to allow more concurrent script executions in OpenSim.
 | 
			
		||||
        //
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// List of threads processing event queue
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private List<Thread> eventQueueThreads = new List<Thread>();
 | 
			
		||||
 | 
			
		||||
        private object queueLock = new object(); // Mutex lock object
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// How many ms to sleep if queue is empty
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private int nothingToDoSleepms = 50;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// How many threads to process queue with
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private int numberOfThreads = 2;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Queue containing events waiting to be executed
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Queue item structure
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private struct QueueItemStruct
 | 
			
		||||
        {
 | 
			
		||||
            public uint localID;
 | 
			
		||||
            public LLUUID itemID;
 | 
			
		||||
            public string functionName;
 | 
			
		||||
            public object[] param;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// List of localID locks for mutex processing of script events
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private List<uint> objectLocks = new List<uint>();
 | 
			
		||||
 | 
			
		||||
        private object tryLockLock = new object(); // Mutex lock object
 | 
			
		||||
 | 
			
		||||
        private ScriptEngine m_ScriptEngine;
 | 
			
		||||
 | 
			
		||||
        public EventQueueManager(ScriptEngine _ScriptEngine)
 | 
			
		||||
        {
 | 
			
		||||
            m_ScriptEngine = _ScriptEngine;
 | 
			
		||||
 | 
			
		||||
            //
 | 
			
		||||
            // Start event queue processing threads (worker threads)
 | 
			
		||||
            //
 | 
			
		||||
            for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++)
 | 
			
		||||
            {
 | 
			
		||||
                Thread EventQueueThread = new Thread(EventQueueThreadLoop);
 | 
			
		||||
                eventQueueThreads.Add(EventQueueThread);
 | 
			
		||||
                EventQueueThread.IsBackground = true;
 | 
			
		||||
                EventQueueThread.Priority = ThreadPriority.BelowNormal;
 | 
			
		||||
                EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
 | 
			
		||||
                EventQueueThread.Start();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~EventQueueManager()
 | 
			
		||||
        {
 | 
			
		||||
            // Kill worker threads
 | 
			
		||||
            foreach (Thread EventQueueThread in new ArrayList(eventQueueThreads))
 | 
			
		||||
            {
 | 
			
		||||
                if (EventQueueThread != null && EventQueueThread.IsAlive == true)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        EventQueueThread.Abort();
 | 
			
		||||
                        EventQueueThread.Join();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception)
 | 
			
		||||
                    {
 | 
			
		||||
                        //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            eventQueueThreads.Clear();
 | 
			
		||||
            // Todo: Clean up our queues
 | 
			
		||||
            eventQueue.Clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Queue processing thread loop
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void EventQueueThreadLoop()
 | 
			
		||||
        {
 | 
			
		||||
            //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned");
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                QueueItemStruct BlankQIS = new QueueItemStruct();
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        QueueItemStruct QIS = BlankQIS;
 | 
			
		||||
                        bool GotItem = false;
 | 
			
		||||
 | 
			
		||||
                        if (eventQueue.Count == 0)
 | 
			
		||||
                        {
 | 
			
		||||
                            // Nothing to do? Sleep a bit waiting for something to do
 | 
			
		||||
                            Thread.Sleep(nothingToDoSleepms);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            // Something in queue, process
 | 
			
		||||
                            //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
 | 
			
		||||
 | 
			
		||||
                            // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
 | 
			
		||||
                            lock (queueLock)
 | 
			
		||||
                            {
 | 
			
		||||
                                GotItem = false;
 | 
			
		||||
                                for (int qc = 0; qc < eventQueue.Count; qc++)
 | 
			
		||||
                                {
 | 
			
		||||
                                    // Get queue item
 | 
			
		||||
                                    QIS = eventQueue.Dequeue();
 | 
			
		||||
 | 
			
		||||
                                    // Check if object is being processed by someone else
 | 
			
		||||
                                    if (TryLock(QIS.localID) == false)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        // Object is already being processed, requeue it
 | 
			
		||||
                                        eventQueue.Enqueue(QIS);
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else
 | 
			
		||||
                                    {
 | 
			
		||||
                                        // We have lock on an object and can process it
 | 
			
		||||
                                        GotItem = true;
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    }
 | 
			
		||||
                                } // go through queue
 | 
			
		||||
                            } // lock
 | 
			
		||||
 | 
			
		||||
                            if (GotItem == true)
 | 
			
		||||
                            {
 | 
			
		||||
                                // Execute function
 | 
			
		||||
                                try
 | 
			
		||||
                                {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
                                    m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n"
 | 
			
		||||
                                                                             + "QIS.localID: " + QIS.localID
 | 
			
		||||
                                                                             + ", QIS.itemID: " + QIS.itemID
 | 
			
		||||
                                                                             + ", QIS.functionName: " + QIS.functionName);
 | 
			
		||||
#endif
 | 
			
		||||
                                    m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID,
 | 
			
		||||
                                                                                QIS.functionName, QIS.param);
 | 
			
		||||
                                }
 | 
			
		||||
                                catch (Exception e)
 | 
			
		||||
                                {
 | 
			
		||||
                                    // DISPLAY ERROR INWORLD
 | 
			
		||||
                                    string text = "Error executing script function \"" + QIS.functionName + "\":\r\n";
 | 
			
		||||
                                    //if (e.InnerException != null)
 | 
			
		||||
                                    //{
 | 
			
		||||
                                    // Send inner exception
 | 
			
		||||
                                    text += e.InnerException.Message.ToString();
 | 
			
		||||
                                    //}
 | 
			
		||||
                                    //else
 | 
			
		||||
                                    //{
 | 
			
		||||
                                    text += "\r\n";
 | 
			
		||||
                                    // Send normal
 | 
			
		||||
                                    text += e.Message.ToString();
 | 
			
		||||
                                    //}
 | 
			
		||||
                                    try
 | 
			
		||||
                                    {
 | 
			
		||||
                                        if (text.Length > 1500)
 | 
			
		||||
                                            text = text.Substring(0, 1500);
 | 
			
		||||
                                        IScriptHost m_host = m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
 | 
			
		||||
                                        //if (m_host != null)
 | 
			
		||||
                                        //{
 | 
			
		||||
                                        m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0,
 | 
			
		||||
                                                                     m_host.AbsolutePosition, m_host.Name, m_host.UUID);
 | 
			
		||||
                                    }
 | 
			
		||||
                                    catch
 | 
			
		||||
                                    {
 | 
			
		||||
                                        //}
 | 
			
		||||
                                        //else
 | 
			
		||||
                                        //{
 | 
			
		||||
                                        // T oconsole
 | 
			
		||||
                                        m_ScriptEngine.Log.Error("ScriptEngine",
 | 
			
		||||
                                                                 "Unable to send text in-world:\r\n" + text);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                finally
 | 
			
		||||
                                {
 | 
			
		||||
                                    ReleaseLock(QIS.localID);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        } // Something in queue
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (ThreadAbortException tae)
 | 
			
		||||
                    {
 | 
			
		||||
                        throw tae;
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception e)
 | 
			
		||||
                    {
 | 
			
		||||
                        m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString());
 | 
			
		||||
                    }
 | 
			
		||||
                } // while
 | 
			
		||||
            } // try
 | 
			
		||||
            catch (ThreadAbortException)
 | 
			
		||||
            {
 | 
			
		||||
                //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Try to get a mutex lock on localID
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        private bool TryLock(uint localID)
 | 
			
		||||
        {
 | 
			
		||||
            lock (tryLockLock)
 | 
			
		||||
            {
 | 
			
		||||
                if (objectLocks.Contains(localID) == true)
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    objectLocks.Add(localID);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Release mutex lock on localID
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        private void ReleaseLock(uint localID)
 | 
			
		||||
        {
 | 
			
		||||
            lock (tryLockLock)
 | 
			
		||||
            {
 | 
			
		||||
                if (objectLocks.Contains(localID) == true)
 | 
			
		||||
                {
 | 
			
		||||
                    objectLocks.Remove(localID);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Add event to event execution queue
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
 | 
			
		||||
        /// <param name="param">Array of parameters to match event mask</param>
 | 
			
		||||
        public void AddToObjectQueue(uint localID, string FunctionName, params object[] param)
 | 
			
		||||
        {
 | 
			
		||||
            // Determine all scripts in Object and add to their queue
 | 
			
		||||
            //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            // Do we have any scripts in this object at all? If not, return
 | 
			
		||||
            if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false)
 | 
			
		||||
            {
 | 
			
		||||
                //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID.");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Dictionary<LLUUID, IScript>.KeyCollection scriptKeys =
 | 
			
		||||
                m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID);
 | 
			
		||||
 | 
			
		||||
            foreach (LLUUID itemID in scriptKeys)
 | 
			
		||||
            {
 | 
			
		||||
                // Add to each script in that object
 | 
			
		||||
                // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter?
 | 
			
		||||
                AddToScriptQueue(localID, itemID, FunctionName, param);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Add event to event execution queue
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        /// <param name="itemID"></param>
 | 
			
		||||
        /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
 | 
			
		||||
        /// <param name="param">Array of parameters to match event mask</param>
 | 
			
		||||
        public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, params object[] param)
 | 
			
		||||
        {
 | 
			
		||||
            lock (queueLock)
 | 
			
		||||
            {
 | 
			
		||||
                // Create a structure and add data
 | 
			
		||||
                QueueItemStruct QIS = new QueueItemStruct();
 | 
			
		||||
                QIS.localID = localID;
 | 
			
		||||
                QIS.itemID = itemID;
 | 
			
		||||
                QIS.functionName = FunctionName;
 | 
			
		||||
                QIS.param = param;
 | 
			
		||||
 | 
			
		||||
                // Add it to queue
 | 
			
		||||
                eventQueue.Enqueue(QIS);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using libsecondlife;
 | 
			
		||||
using OpenSim.Framework;
 | 
			
		||||
using OpenSim.Region.Environment.Scenes.Scripting;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// EventQueueManager handles event queues
 | 
			
		||||
    /// Events are queued and executed in separate thread
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public class EventQueueManager
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine".
 | 
			
		||||
        //
 | 
			
		||||
        // Class purpose is to queue and execute functions that are received by "EventManager":
 | 
			
		||||
        //   - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution.
 | 
			
		||||
        //   - allowing us to prioritize and control execution of script functions.
 | 
			
		||||
        // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety.
 | 
			
		||||
        //
 | 
			
		||||
        // 1. Hold an execution queue for scripts
 | 
			
		||||
        // 2. Use threads to process queue, each thread executes one script function on each pass.
 | 
			
		||||
        // 3. Catch any script error and process it
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        // Notes:
 | 
			
		||||
        // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts.
 | 
			
		||||
        //   Not noticeable unless server is under high load.
 | 
			
		||||
        // * This class contains the number of threads used for script executions. Since we are not microthreading scripts yet,
 | 
			
		||||
        //   increase number of threads to allow more concurrent script executions in OpenSim.
 | 
			
		||||
        //
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// List of threads processing event queue
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private List<Thread> eventQueueThreads = new List<Thread>();
 | 
			
		||||
 | 
			
		||||
        private object queueLock = new object(); // Mutex lock object
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// How many ms to sleep if queue is empty
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private int nothingToDoSleepms = 50;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// How many threads to process queue with
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private int numberOfThreads = 2;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Queue containing events waiting to be executed
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Queue item structure
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private struct QueueItemStruct
 | 
			
		||||
        {
 | 
			
		||||
            public uint localID;
 | 
			
		||||
            public LLUUID itemID;
 | 
			
		||||
            public string functionName;
 | 
			
		||||
            public object[] param;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// List of localID locks for mutex processing of script events
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private List<uint> objectLocks = new List<uint>();
 | 
			
		||||
 | 
			
		||||
        private object tryLockLock = new object(); // Mutex lock object
 | 
			
		||||
 | 
			
		||||
        private ScriptEngine m_ScriptEngine;
 | 
			
		||||
 | 
			
		||||
        public EventQueueManager(ScriptEngine _ScriptEngine)
 | 
			
		||||
        {
 | 
			
		||||
            m_ScriptEngine = _ScriptEngine;
 | 
			
		||||
 | 
			
		||||
            //
 | 
			
		||||
            // Start event queue processing threads (worker threads)
 | 
			
		||||
            //
 | 
			
		||||
            for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++)
 | 
			
		||||
            {
 | 
			
		||||
                Thread EventQueueThread = new Thread(EventQueueThreadLoop);
 | 
			
		||||
                eventQueueThreads.Add(EventQueueThread);
 | 
			
		||||
                EventQueueThread.IsBackground = true;
 | 
			
		||||
                EventQueueThread.Priority = ThreadPriority.BelowNormal;
 | 
			
		||||
                EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
 | 
			
		||||
                EventQueueThread.Start();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~EventQueueManager()
 | 
			
		||||
        {
 | 
			
		||||
            // Kill worker threads
 | 
			
		||||
            foreach (Thread EventQueueThread in new ArrayList(eventQueueThreads))
 | 
			
		||||
            {
 | 
			
		||||
                if (EventQueueThread != null && EventQueueThread.IsAlive == true)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        EventQueueThread.Abort();
 | 
			
		||||
                        EventQueueThread.Join();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception)
 | 
			
		||||
                    {
 | 
			
		||||
                        //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            eventQueueThreads.Clear();
 | 
			
		||||
            // Todo: Clean up our queues
 | 
			
		||||
            eventQueue.Clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Queue processing thread loop
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void EventQueueThreadLoop()
 | 
			
		||||
        {
 | 
			
		||||
            //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned");
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                QueueItemStruct BlankQIS = new QueueItemStruct();
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        QueueItemStruct QIS = BlankQIS;
 | 
			
		||||
                        bool GotItem = false;
 | 
			
		||||
 | 
			
		||||
                        if (eventQueue.Count == 0)
 | 
			
		||||
                        {
 | 
			
		||||
                            // Nothing to do? Sleep a bit waiting for something to do
 | 
			
		||||
                            Thread.Sleep(nothingToDoSleepms);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            // Something in queue, process
 | 
			
		||||
                            //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
 | 
			
		||||
 | 
			
		||||
                            // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
 | 
			
		||||
                            lock (queueLock)
 | 
			
		||||
                            {
 | 
			
		||||
                                GotItem = false;
 | 
			
		||||
                                for (int qc = 0; qc < eventQueue.Count; qc++)
 | 
			
		||||
                                {
 | 
			
		||||
                                    // Get queue item
 | 
			
		||||
                                    QIS = eventQueue.Dequeue();
 | 
			
		||||
 | 
			
		||||
                                    // Check if object is being processed by someone else
 | 
			
		||||
                                    if (TryLock(QIS.localID) == false)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        // Object is already being processed, requeue it
 | 
			
		||||
                                        eventQueue.Enqueue(QIS);
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else
 | 
			
		||||
                                    {
 | 
			
		||||
                                        // We have lock on an object and can process it
 | 
			
		||||
                                        GotItem = true;
 | 
			
		||||
                                        break;
 | 
			
		||||
                                    }
 | 
			
		||||
                                } // go through queue
 | 
			
		||||
                            } // lock
 | 
			
		||||
 | 
			
		||||
                            if (GotItem == true)
 | 
			
		||||
                            {
 | 
			
		||||
                                // Execute function
 | 
			
		||||
                                try
 | 
			
		||||
                                {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
                                    m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n"
 | 
			
		||||
                                                                             + "QIS.localID: " + QIS.localID
 | 
			
		||||
                                                                             + ", QIS.itemID: " + QIS.itemID
 | 
			
		||||
                                                                             + ", QIS.functionName: " + QIS.functionName);
 | 
			
		||||
#endif
 | 
			
		||||
                                    m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID,
 | 
			
		||||
                                                                                QIS.functionName, QIS.param);
 | 
			
		||||
                                }
 | 
			
		||||
                                catch (Exception e)
 | 
			
		||||
                                {
 | 
			
		||||
                                    // DISPLAY ERROR INWORLD
 | 
			
		||||
                                    string text = "Error executing script function \"" + QIS.functionName + "\":\r\n";
 | 
			
		||||
                                    //if (e.InnerException != null)
 | 
			
		||||
                                    //{
 | 
			
		||||
                                    // Send inner exception
 | 
			
		||||
                                    text += e.InnerException.Message.ToString();
 | 
			
		||||
                                    //}
 | 
			
		||||
                                    //else
 | 
			
		||||
                                    //{
 | 
			
		||||
                                    text += "\r\n";
 | 
			
		||||
                                    // Send normal
 | 
			
		||||
                                    text += e.Message.ToString();
 | 
			
		||||
                                    //}
 | 
			
		||||
                                    try
 | 
			
		||||
                                    {
 | 
			
		||||
                                        if (text.Length > 1500)
 | 
			
		||||
                                            text = text.Substring(0, 1500);
 | 
			
		||||
                                        IScriptHost m_host = m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
 | 
			
		||||
                                        //if (m_host != null)
 | 
			
		||||
                                        //{
 | 
			
		||||
                                        m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0,
 | 
			
		||||
                                                                     m_host.AbsolutePosition, m_host.Name, m_host.UUID);
 | 
			
		||||
                                    }
 | 
			
		||||
                                    catch
 | 
			
		||||
                                    {
 | 
			
		||||
                                        //}
 | 
			
		||||
                                        //else
 | 
			
		||||
                                        //{
 | 
			
		||||
                                        // T oconsole
 | 
			
		||||
                                        m_ScriptEngine.Log.Error("ScriptEngine",
 | 
			
		||||
                                                                 "Unable to send text in-world:\r\n" + text);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                finally
 | 
			
		||||
                                {
 | 
			
		||||
                                    ReleaseLock(QIS.localID);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        } // Something in queue
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (ThreadAbortException tae)
 | 
			
		||||
                    {
 | 
			
		||||
                        throw tae;
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception e)
 | 
			
		||||
                    {
 | 
			
		||||
                        m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString());
 | 
			
		||||
                    }
 | 
			
		||||
                } // while
 | 
			
		||||
            } // try
 | 
			
		||||
            catch (ThreadAbortException)
 | 
			
		||||
            {
 | 
			
		||||
                //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Try to get a mutex lock on localID
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        private bool TryLock(uint localID)
 | 
			
		||||
        {
 | 
			
		||||
            lock (tryLockLock)
 | 
			
		||||
            {
 | 
			
		||||
                if (objectLocks.Contains(localID) == true)
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    objectLocks.Add(localID);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Release mutex lock on localID
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        private void ReleaseLock(uint localID)
 | 
			
		||||
        {
 | 
			
		||||
            lock (tryLockLock)
 | 
			
		||||
            {
 | 
			
		||||
                if (objectLocks.Contains(localID) == true)
 | 
			
		||||
                {
 | 
			
		||||
                    objectLocks.Remove(localID);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Add event to event execution queue
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
 | 
			
		||||
        /// <param name="param">Array of parameters to match event mask</param>
 | 
			
		||||
        public void AddToObjectQueue(uint localID, string FunctionName, params object[] param)
 | 
			
		||||
        {
 | 
			
		||||
            // Determine all scripts in Object and add to their queue
 | 
			
		||||
            //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            // Do we have any scripts in this object at all? If not, return
 | 
			
		||||
            if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false)
 | 
			
		||||
            {
 | 
			
		||||
                //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID.");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Dictionary<LLUUID, IScript>.KeyCollection scriptKeys =
 | 
			
		||||
                m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID);
 | 
			
		||||
 | 
			
		||||
            foreach (LLUUID itemID in scriptKeys)
 | 
			
		||||
            {
 | 
			
		||||
                // Add to each script in that object
 | 
			
		||||
                // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter?
 | 
			
		||||
                AddToScriptQueue(localID, itemID, FunctionName, param);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Add event to event execution queue
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        /// <param name="itemID"></param>
 | 
			
		||||
        /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
 | 
			
		||||
        /// <param name="param">Array of parameters to match event mask</param>
 | 
			
		||||
        public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, params object[] param)
 | 
			
		||||
        {
 | 
			
		||||
            lock (queueLock)
 | 
			
		||||
            {
 | 
			
		||||
                // Create a structure and add data
 | 
			
		||||
                QueueItemStruct QIS = new QueueItemStruct();
 | 
			
		||||
                QIS.localID = localID;
 | 
			
		||||
                QIS.itemID = itemID;
 | 
			
		||||
                QIS.functionName = FunctionName;
 | 
			
		||||
                QIS.param = param;
 | 
			
		||||
 | 
			
		||||
                // Add it to queue
 | 
			
		||||
                eventQueue.Enqueue(QIS);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,295 +1,295 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using libsecondlife;
 | 
			
		||||
using OpenSim.Region.Environment.Interfaces;
 | 
			
		||||
using OpenSim.Region.Environment.Modules;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class LSLLongCmdHandler
 | 
			
		||||
    {
 | 
			
		||||
        private Thread cmdHandlerThread;
 | 
			
		||||
        private int cmdHandlerThreadCycleSleepms = 100;
 | 
			
		||||
 | 
			
		||||
        private ScriptEngine m_ScriptEngine;
 | 
			
		||||
 | 
			
		||||
        public LSLLongCmdHandler(ScriptEngine _ScriptEngine)
 | 
			
		||||
        {
 | 
			
		||||
            m_ScriptEngine = _ScriptEngine;
 | 
			
		||||
 | 
			
		||||
            // Start the thread that will be doing the work
 | 
			
		||||
            cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
 | 
			
		||||
            cmdHandlerThread.Name = "CmdHandlerThread";
 | 
			
		||||
            cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
 | 
			
		||||
            cmdHandlerThread.IsBackground = true;
 | 
			
		||||
            cmdHandlerThread.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~LSLLongCmdHandler()
 | 
			
		||||
        {
 | 
			
		||||
            // Shut down thread
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (cmdHandlerThread != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (cmdHandlerThread.IsAlive == true)
 | 
			
		||||
                    {
 | 
			
		||||
                        cmdHandlerThread.Abort();
 | 
			
		||||
                        cmdHandlerThread.Join();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void CmdHandlerThreadLoop()
 | 
			
		||||
        {
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                // Check timers
 | 
			
		||||
                CheckTimerEvents();
 | 
			
		||||
                Thread.Sleep(25);
 | 
			
		||||
                // Check HttpRequests
 | 
			
		||||
                CheckHttpRequests();
 | 
			
		||||
                Thread.Sleep(25);
 | 
			
		||||
                // Check XMLRPCRequests
 | 
			
		||||
                CheckXMLRPCRequests();
 | 
			
		||||
                Thread.Sleep(25);
 | 
			
		||||
                // Check Listeners
 | 
			
		||||
                CheckListeners();
 | 
			
		||||
                Thread.Sleep(25);
 | 
			
		||||
 | 
			
		||||
                // Sleep before next cycle
 | 
			
		||||
                //Thread.Sleep(cmdHandlerThreadCycleSleepms);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Remove a specific script (and all its pending commands)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="m_localID"></param>
 | 
			
		||||
        /// <param name="m_itemID"></param>
 | 
			
		||||
        public void RemoveScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Remove a specific script
 | 
			
		||||
 | 
			
		||||
            // Remove from: Timers
 | 
			
		||||
            UnSetTimerEvents(localID, itemID);
 | 
			
		||||
            // Remove from: HttpRequest
 | 
			
		||||
            IHttpRequests iHttpReq =
 | 
			
		||||
                m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
 | 
			
		||||
            iHttpReq.StopHttpRequest(localID, itemID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region TIMER
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // TIMER
 | 
			
		||||
        //
 | 
			
		||||
        private class TimerClass
 | 
			
		||||
        {
 | 
			
		||||
            public uint localID;
 | 
			
		||||
            public LLUUID itemID;
 | 
			
		||||
            public double interval;
 | 
			
		||||
            public DateTime next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private List<TimerClass> Timers = new List<TimerClass>();
 | 
			
		||||
        private object TimerListLock = new object();
 | 
			
		||||
 | 
			
		||||
        public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("SetTimerEvent");
 | 
			
		||||
 | 
			
		||||
            // Always remove first, in case this is a re-set
 | 
			
		||||
            UnSetTimerEvents(m_localID, m_itemID);
 | 
			
		||||
            if (sec == 0) // Disabling timer
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            // Add to timer
 | 
			
		||||
            TimerClass ts = new TimerClass();
 | 
			
		||||
            ts.localID = m_localID;
 | 
			
		||||
            ts.itemID = m_itemID;
 | 
			
		||||
            ts.interval = sec;
 | 
			
		||||
            ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
 | 
			
		||||
            lock (TimerListLock)
 | 
			
		||||
            {
 | 
			
		||||
                Timers.Add(ts);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Remove from timer
 | 
			
		||||
            lock (TimerListLock)
 | 
			
		||||
            {
 | 
			
		||||
                List<TimerClass> NewTimers = new List<TimerClass>();
 | 
			
		||||
                foreach (TimerClass ts in Timers)
 | 
			
		||||
                {
 | 
			
		||||
                    if (ts.localID != m_localID && ts.itemID != m_itemID)
 | 
			
		||||
                    {
 | 
			
		||||
                        NewTimers.Add(ts);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                Timers.Clear();
 | 
			
		||||
                Timers = NewTimers;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void CheckTimerEvents()
 | 
			
		||||
        {
 | 
			
		||||
            // Nothing to do here?
 | 
			
		||||
            if (Timers.Count == 0)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            lock (TimerListLock)
 | 
			
		||||
            {
 | 
			
		||||
                // Go through all timers
 | 
			
		||||
                foreach (TimerClass ts in Timers)
 | 
			
		||||
                {
 | 
			
		||||
                    // Time has passed?
 | 
			
		||||
                    if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
 | 
			
		||||
                    {
 | 
			
		||||
                        // Add it to queue
 | 
			
		||||
                        m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer",
 | 
			
		||||
                                                                            new object[] {});
 | 
			
		||||
                        // set next interval
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                        ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } // lock
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region HTTP REQUEST
 | 
			
		||||
 | 
			
		||||
        public void CheckHttpRequests()
 | 
			
		||||
        {
 | 
			
		||||
            if (m_ScriptEngine.World == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            IHttpRequests iHttpReq =
 | 
			
		||||
                m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
 | 
			
		||||
 | 
			
		||||
            HttpRequestClass httpInfo = null;
 | 
			
		||||
 | 
			
		||||
            if (iHttpReq != null)
 | 
			
		||||
                httpInfo = iHttpReq.GetNextCompletedRequest();
 | 
			
		||||
 | 
			
		||||
            while (httpInfo != null)
 | 
			
		||||
            {
 | 
			
		||||
                //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status);
 | 
			
		||||
 | 
			
		||||
                // Deliver data to prim's remote_data handler
 | 
			
		||||
                //
 | 
			
		||||
                // TODO: Returning null for metadata, since the lsl function
 | 
			
		||||
                // only returns the byte for HTTP_BODY_TRUNCATED, which is not
 | 
			
		||||
                // implemented here yet anyway.  Should be fixed if/when maxsize
 | 
			
		||||
                // is supported
 | 
			
		||||
 | 
			
		||||
                object[] resobj = new object[]
 | 
			
		||||
                    {
 | 
			
		||||
                        httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
 | 
			
		||||
                    httpInfo.localID, httpInfo.itemID, "http_response", resobj
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                httpInfo.Stop();
 | 
			
		||||
                httpInfo = null;
 | 
			
		||||
 | 
			
		||||
                httpInfo = iHttpReq.GetNextCompletedRequest();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        public void CheckXMLRPCRequests()
 | 
			
		||||
        {
 | 
			
		||||
            if (m_ScriptEngine.World == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
 | 
			
		||||
 | 
			
		||||
            if (xmlrpc != null)
 | 
			
		||||
            {
 | 
			
		||||
                while (xmlrpc.hasRequests())
 | 
			
		||||
                {
 | 
			
		||||
                    RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
 | 
			
		||||
                    //Console.WriteLine("PICKED REQUEST");
 | 
			
		||||
 | 
			
		||||
                    //Deliver data to prim's remote_data handler
 | 
			
		||||
                    object[] resobj = new object[]
 | 
			
		||||
                        {
 | 
			
		||||
                            2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), "",
 | 
			
		||||
                            rInfo.GetIntValue(),
 | 
			
		||||
                            rInfo.GetStrVal()
 | 
			
		||||
                        };
 | 
			
		||||
                    m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
 | 
			
		||||
                        rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", resobj
 | 
			
		||||
                        );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void CheckListeners()
 | 
			
		||||
        {
 | 
			
		||||
            if (m_ScriptEngine.World == null)
 | 
			
		||||
                return;
 | 
			
		||||
            IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
 | 
			
		||||
 | 
			
		||||
            while (comms.HasMessages())
 | 
			
		||||
            {
 | 
			
		||||
                ListenerInfo lInfo = comms.GetNextMessage();
 | 
			
		||||
 | 
			
		||||
                //Deliver data to prim's listen handler
 | 
			
		||||
                object[] resobj = new object[]
 | 
			
		||||
                    {
 | 
			
		||||
                        lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
 | 
			
		||||
                    lInfo.GetLocalID(), lInfo.GetItemID(), "listen", resobj
 | 
			
		||||
                    );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using libsecondlife;
 | 
			
		||||
using OpenSim.Region.Environment.Interfaces;
 | 
			
		||||
using OpenSim.Region.Environment.Modules;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class LSLLongCmdHandler
 | 
			
		||||
    {
 | 
			
		||||
        private Thread cmdHandlerThread;
 | 
			
		||||
        private int cmdHandlerThreadCycleSleepms = 100;
 | 
			
		||||
 | 
			
		||||
        private ScriptEngine m_ScriptEngine;
 | 
			
		||||
 | 
			
		||||
        public LSLLongCmdHandler(ScriptEngine _ScriptEngine)
 | 
			
		||||
        {
 | 
			
		||||
            m_ScriptEngine = _ScriptEngine;
 | 
			
		||||
 | 
			
		||||
            // Start the thread that will be doing the work
 | 
			
		||||
            cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
 | 
			
		||||
            cmdHandlerThread.Name = "CmdHandlerThread";
 | 
			
		||||
            cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
 | 
			
		||||
            cmdHandlerThread.IsBackground = true;
 | 
			
		||||
            cmdHandlerThread.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~LSLLongCmdHandler()
 | 
			
		||||
        {
 | 
			
		||||
            // Shut down thread
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (cmdHandlerThread != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (cmdHandlerThread.IsAlive == true)
 | 
			
		||||
                    {
 | 
			
		||||
                        cmdHandlerThread.Abort();
 | 
			
		||||
                        cmdHandlerThread.Join();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void CmdHandlerThreadLoop()
 | 
			
		||||
        {
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                // Check timers
 | 
			
		||||
                CheckTimerEvents();
 | 
			
		||||
                Thread.Sleep(25);
 | 
			
		||||
                // Check HttpRequests
 | 
			
		||||
                CheckHttpRequests();
 | 
			
		||||
                Thread.Sleep(25);
 | 
			
		||||
                // Check XMLRPCRequests
 | 
			
		||||
                CheckXMLRPCRequests();
 | 
			
		||||
                Thread.Sleep(25);
 | 
			
		||||
                // Check Listeners
 | 
			
		||||
                CheckListeners();
 | 
			
		||||
                Thread.Sleep(25);
 | 
			
		||||
 | 
			
		||||
                // Sleep before next cycle
 | 
			
		||||
                //Thread.Sleep(cmdHandlerThreadCycleSleepms);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Remove a specific script (and all its pending commands)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="m_localID"></param>
 | 
			
		||||
        /// <param name="m_itemID"></param>
 | 
			
		||||
        public void RemoveScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Remove a specific script
 | 
			
		||||
 | 
			
		||||
            // Remove from: Timers
 | 
			
		||||
            UnSetTimerEvents(localID, itemID);
 | 
			
		||||
            // Remove from: HttpRequest
 | 
			
		||||
            IHttpRequests iHttpReq =
 | 
			
		||||
                m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
 | 
			
		||||
            iHttpReq.StopHttpRequest(localID, itemID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region TIMER
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // TIMER
 | 
			
		||||
        //
 | 
			
		||||
        private class TimerClass
 | 
			
		||||
        {
 | 
			
		||||
            public uint localID;
 | 
			
		||||
            public LLUUID itemID;
 | 
			
		||||
            public double interval;
 | 
			
		||||
            public DateTime next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private List<TimerClass> Timers = new List<TimerClass>();
 | 
			
		||||
        private object TimerListLock = new object();
 | 
			
		||||
 | 
			
		||||
        public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
 | 
			
		||||
        {
 | 
			
		||||
            Console.WriteLine("SetTimerEvent");
 | 
			
		||||
 | 
			
		||||
            // Always remove first, in case this is a re-set
 | 
			
		||||
            UnSetTimerEvents(m_localID, m_itemID);
 | 
			
		||||
            if (sec == 0) // Disabling timer
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            // Add to timer
 | 
			
		||||
            TimerClass ts = new TimerClass();
 | 
			
		||||
            ts.localID = m_localID;
 | 
			
		||||
            ts.itemID = m_itemID;
 | 
			
		||||
            ts.interval = sec;
 | 
			
		||||
            ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
 | 
			
		||||
            lock (TimerListLock)
 | 
			
		||||
            {
 | 
			
		||||
                Timers.Add(ts);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Remove from timer
 | 
			
		||||
            lock (TimerListLock)
 | 
			
		||||
            {
 | 
			
		||||
                List<TimerClass> NewTimers = new List<TimerClass>();
 | 
			
		||||
                foreach (TimerClass ts in Timers)
 | 
			
		||||
                {
 | 
			
		||||
                    if (ts.localID != m_localID && ts.itemID != m_itemID)
 | 
			
		||||
                    {
 | 
			
		||||
                        NewTimers.Add(ts);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                Timers.Clear();
 | 
			
		||||
                Timers = NewTimers;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void CheckTimerEvents()
 | 
			
		||||
        {
 | 
			
		||||
            // Nothing to do here?
 | 
			
		||||
            if (Timers.Count == 0)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            lock (TimerListLock)
 | 
			
		||||
            {
 | 
			
		||||
                // Go through all timers
 | 
			
		||||
                foreach (TimerClass ts in Timers)
 | 
			
		||||
                {
 | 
			
		||||
                    // Time has passed?
 | 
			
		||||
                    if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
 | 
			
		||||
                    {
 | 
			
		||||
                        // Add it to queue
 | 
			
		||||
                        m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer",
 | 
			
		||||
                                                                            new object[] {});
 | 
			
		||||
                        // set next interval
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                        ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } // lock
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region HTTP REQUEST
 | 
			
		||||
 | 
			
		||||
        public void CheckHttpRequests()
 | 
			
		||||
        {
 | 
			
		||||
            if (m_ScriptEngine.World == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            IHttpRequests iHttpReq =
 | 
			
		||||
                m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
 | 
			
		||||
 | 
			
		||||
            HttpRequestClass httpInfo = null;
 | 
			
		||||
 | 
			
		||||
            if (iHttpReq != null)
 | 
			
		||||
                httpInfo = iHttpReq.GetNextCompletedRequest();
 | 
			
		||||
 | 
			
		||||
            while (httpInfo != null)
 | 
			
		||||
            {
 | 
			
		||||
                //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status);
 | 
			
		||||
 | 
			
		||||
                // Deliver data to prim's remote_data handler
 | 
			
		||||
                //
 | 
			
		||||
                // TODO: Returning null for metadata, since the lsl function
 | 
			
		||||
                // only returns the byte for HTTP_BODY_TRUNCATED, which is not
 | 
			
		||||
                // implemented here yet anyway.  Should be fixed if/when maxsize
 | 
			
		||||
                // is supported
 | 
			
		||||
 | 
			
		||||
                object[] resobj = new object[]
 | 
			
		||||
                    {
 | 
			
		||||
                        httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
 | 
			
		||||
                    httpInfo.localID, httpInfo.itemID, "http_response", resobj
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                httpInfo.Stop();
 | 
			
		||||
                httpInfo = null;
 | 
			
		||||
 | 
			
		||||
                httpInfo = iHttpReq.GetNextCompletedRequest();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        public void CheckXMLRPCRequests()
 | 
			
		||||
        {
 | 
			
		||||
            if (m_ScriptEngine.World == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
 | 
			
		||||
 | 
			
		||||
            if (xmlrpc != null)
 | 
			
		||||
            {
 | 
			
		||||
                while (xmlrpc.hasRequests())
 | 
			
		||||
                {
 | 
			
		||||
                    RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
 | 
			
		||||
                    //Console.WriteLine("PICKED REQUEST");
 | 
			
		||||
 | 
			
		||||
                    //Deliver data to prim's remote_data handler
 | 
			
		||||
                    object[] resobj = new object[]
 | 
			
		||||
                        {
 | 
			
		||||
                            2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), "",
 | 
			
		||||
                            rInfo.GetIntValue(),
 | 
			
		||||
                            rInfo.GetStrVal()
 | 
			
		||||
                        };
 | 
			
		||||
                    m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
 | 
			
		||||
                        rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", resobj
 | 
			
		||||
                        );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void CheckListeners()
 | 
			
		||||
        {
 | 
			
		||||
            if (m_ScriptEngine.World == null)
 | 
			
		||||
                return;
 | 
			
		||||
            IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
 | 
			
		||||
 | 
			
		||||
            while (comms.HasMessages())
 | 
			
		||||
            {
 | 
			
		||||
                ListenerInfo lInfo = comms.GetNextMessage();
 | 
			
		||||
 | 
			
		||||
                //Deliver data to prim's listen handler
 | 
			
		||||
                object[] resobj = new object[]
 | 
			
		||||
                    {
 | 
			
		||||
                        lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
 | 
			
		||||
                    lInfo.GetLocalID(), lInfo.GetItemID(), "listen", resobj
 | 
			
		||||
                    );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,132 +1,132 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using Nini.Config;
 | 
			
		||||
using OpenSim.Framework.Console;
 | 
			
		||||
using OpenSim.Region.Environment.Interfaces;
 | 
			
		||||
using OpenSim.Region.Environment.Scenes;
 | 
			
		||||
using OpenSim.Region.ScriptEngine.Common;
 | 
			
		||||
using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// This is the root object for ScriptEngine. Objects access each other trough this class.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// 
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public abstract class ScriptEngine : IRegionModule, OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.ScriptEngine
 | 
			
		||||
    {
 | 
			
		||||
        public Scene World;
 | 
			
		||||
        public EventManager m_EventManager; // Handles and queues incoming events from OpenSim
 | 
			
		||||
        public EventQueueManager m_EventQueueManager; // Executes events
 | 
			
		||||
        public ScriptManager m_ScriptManager; // Load, unload and execute scripts
 | 
			
		||||
        public AppDomainManager m_AppDomainManager;
 | 
			
		||||
        public LSLLongCmdHandler m_LSLLongCmdHandler;
 | 
			
		||||
 | 
			
		||||
        public ScriptManager GetScriptManager()
 | 
			
		||||
        {
 | 
			
		||||
            return _GetScriptManager();
 | 
			
		||||
        }
 | 
			
		||||
        public abstract ScriptManager _GetScriptManager();
 | 
			
		||||
 | 
			
		||||
        private LogBase m_log;
 | 
			
		||||
 | 
			
		||||
        public ScriptEngine()
 | 
			
		||||
        {
 | 
			
		||||
            //Common.SendToDebug("ScriptEngine Object Initialized");
 | 
			
		||||
            Common.mySE = this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public LogBase Log
 | 
			
		||||
        {
 | 
			
		||||
            get { return m_log; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void InitializeEngine(Scene Sceneworld, LogBase logger, bool HookUpToServer, ScriptManager newScriptManager)
 | 
			
		||||
        {
 | 
			
		||||
            World = Sceneworld;
 | 
			
		||||
            m_log = logger;
 | 
			
		||||
 | 
			
		||||
            Log.Verbose("ScriptEngine", "DotNet & LSL ScriptEngine initializing");
 | 
			
		||||
 | 
			
		||||
            //m_logger.Status("ScriptEngine", "InitializeEngine");
 | 
			
		||||
 | 
			
		||||
            // Create all objects we'll be using
 | 
			
		||||
            m_EventQueueManager = new EventQueueManager(this);
 | 
			
		||||
            m_EventManager = new EventManager(this, HookUpToServer);
 | 
			
		||||
            m_ScriptManager = newScriptManager;
 | 
			
		||||
            //m_ScriptManager = new ScriptManager(this);
 | 
			
		||||
            m_AppDomainManager = new AppDomainManager();
 | 
			
		||||
            m_LSLLongCmdHandler = new LSLLongCmdHandler(this);
 | 
			
		||||
 | 
			
		||||
            // Should we iterate the region for scripts that needs starting?
 | 
			
		||||
            // Or can we assume we are loaded before anything else so we can use proper events?
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Shutdown()
 | 
			
		||||
        {
 | 
			
		||||
            // We are shutting down
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ScriptServerInterfaces.RemoteEvents ScriptServerInterfaces.ScriptEngine.EventManager()
 | 
			
		||||
        {
 | 
			
		||||
            return this.m_EventManager;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region IRegionModule
 | 
			
		||||
 | 
			
		||||
        public abstract void Initialise(Scene scene, IConfigSource config);
 | 
			
		||||
        
 | 
			
		||||
        public void PostInitialise()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Close()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string Name
 | 
			
		||||
        {
 | 
			
		||||
            get { return "DotNetEngine"; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool IsSharedModule
 | 
			
		||||
        {
 | 
			
		||||
            get { return false; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using Nini.Config;
 | 
			
		||||
using OpenSim.Framework.Console;
 | 
			
		||||
using OpenSim.Region.Environment.Interfaces;
 | 
			
		||||
using OpenSim.Region.Environment.Scenes;
 | 
			
		||||
using OpenSim.Region.ScriptEngine.Common;
 | 
			
		||||
using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// This is the root object for ScriptEngine. Objects access each other trough this class.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// 
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public abstract class ScriptEngine : IRegionModule, OpenSim.Region.ScriptEngine.Common.ScriptServerInterfaces.ScriptEngine
 | 
			
		||||
    {
 | 
			
		||||
        public Scene World;
 | 
			
		||||
        public EventManager m_EventManager; // Handles and queues incoming events from OpenSim
 | 
			
		||||
        public EventQueueManager m_EventQueueManager; // Executes events
 | 
			
		||||
        public ScriptManager m_ScriptManager; // Load, unload and execute scripts
 | 
			
		||||
        public AppDomainManager m_AppDomainManager;
 | 
			
		||||
        public LSLLongCmdHandler m_LSLLongCmdHandler;
 | 
			
		||||
 | 
			
		||||
        public ScriptManager GetScriptManager()
 | 
			
		||||
        {
 | 
			
		||||
            return _GetScriptManager();
 | 
			
		||||
        }
 | 
			
		||||
        public abstract ScriptManager _GetScriptManager();
 | 
			
		||||
 | 
			
		||||
        private LogBase m_log;
 | 
			
		||||
 | 
			
		||||
        public ScriptEngine()
 | 
			
		||||
        {
 | 
			
		||||
            //Common.SendToDebug("ScriptEngine Object Initialized");
 | 
			
		||||
            Common.mySE = this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public LogBase Log
 | 
			
		||||
        {
 | 
			
		||||
            get { return m_log; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void InitializeEngine(Scene Sceneworld, LogBase logger, bool HookUpToServer, ScriptManager newScriptManager)
 | 
			
		||||
        {
 | 
			
		||||
            World = Sceneworld;
 | 
			
		||||
            m_log = logger;
 | 
			
		||||
 | 
			
		||||
            Log.Verbose("ScriptEngine", "DotNet & LSL ScriptEngine initializing");
 | 
			
		||||
 | 
			
		||||
            //m_logger.Status("ScriptEngine", "InitializeEngine");
 | 
			
		||||
 | 
			
		||||
            // Create all objects we'll be using
 | 
			
		||||
            m_EventQueueManager = new EventQueueManager(this);
 | 
			
		||||
            m_EventManager = new EventManager(this, HookUpToServer);
 | 
			
		||||
            m_ScriptManager = newScriptManager;
 | 
			
		||||
            //m_ScriptManager = new ScriptManager(this);
 | 
			
		||||
            m_AppDomainManager = new AppDomainManager();
 | 
			
		||||
            m_LSLLongCmdHandler = new LSLLongCmdHandler(this);
 | 
			
		||||
 | 
			
		||||
            // Should we iterate the region for scripts that needs starting?
 | 
			
		||||
            // Or can we assume we are loaded before anything else so we can use proper events?
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Shutdown()
 | 
			
		||||
        {
 | 
			
		||||
            // We are shutting down
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ScriptServerInterfaces.RemoteEvents ScriptServerInterfaces.ScriptEngine.EventManager()
 | 
			
		||||
        {
 | 
			
		||||
            return this.m_EventManager;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region IRegionModule
 | 
			
		||||
 | 
			
		||||
        public abstract void Initialise(Scene scene, IConfigSource config);
 | 
			
		||||
        
 | 
			
		||||
        public void PostInitialise()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Close()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string Name
 | 
			
		||||
        {
 | 
			
		||||
            get { return "DotNetEngine"; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool IsSharedModule
 | 
			
		||||
        {
 | 
			
		||||
            get { return false; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,348 +1,348 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Runtime.Serialization.Formatters.Binary;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using libsecondlife;
 | 
			
		||||
using OpenSim.Framework;
 | 
			
		||||
using OpenSim.Region.Environment.Scenes;
 | 
			
		||||
using OpenSim.Region.ScriptEngine.Common;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Loads scripts
 | 
			
		||||
    /// Compiles them if necessary
 | 
			
		||||
    /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// 
 | 
			
		||||
 | 
			
		||||
    // This class is as close as you get to the script without being inside script class. It handles all the dirty work for other classes.
 | 
			
		||||
    // * Keeps track of running scripts
 | 
			
		||||
    // * Compiles script if necessary (through "Compiler")
 | 
			
		||||
    // * Loads script (through "AppDomainManager" called from for example "EventQueueManager")
 | 
			
		||||
    // * Executes functions inside script (called from for example "EventQueueManager" class)
 | 
			
		||||
    // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager")
 | 
			
		||||
    // * Dedicated load/unload thread, and queues loading/unloading.
 | 
			
		||||
    //   This so that scripts starting or stopping will not slow down other theads or whole system.
 | 
			
		||||
    //
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public abstract class ScriptManager
 | 
			
		||||
    {
 | 
			
		||||
        #region Declares
 | 
			
		||||
 | 
			
		||||
        private Thread scriptLoadUnloadThread;
 | 
			
		||||
        private int scriptLoadUnloadThread_IdleSleepms = 100;
 | 
			
		||||
        private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Load/Unload structure
 | 
			
		||||
        private struct LUStruct
 | 
			
		||||
        {
 | 
			
		||||
            public uint localID;
 | 
			
		||||
            public LLUUID itemID;
 | 
			
		||||
            public string script;
 | 
			
		||||
            public LUType Action;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private enum LUType
 | 
			
		||||
        {
 | 
			
		||||
            Unknown = 0,
 | 
			
		||||
            Load = 1,
 | 
			
		||||
            Unload = 2
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Object<string, Script<string, script>>
 | 
			
		||||
        // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
 | 
			
		||||
        // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
 | 
			
		||||
        public Dictionary<uint, Dictionary<LLUUID, IScript>> Scripts =
 | 
			
		||||
            new Dictionary<uint, Dictionary<LLUUID, IScript>>();
 | 
			
		||||
 | 
			
		||||
        public Scene World
 | 
			
		||||
        {
 | 
			
		||||
            get { return m_scriptEngine.World; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Object init/shutdown
 | 
			
		||||
 | 
			
		||||
        public ScriptEngineBase.ScriptEngine m_scriptEngine;
 | 
			
		||||
 | 
			
		||||
        public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine)
 | 
			
		||||
        {
 | 
			
		||||
            m_scriptEngine = scriptEngine;
 | 
			
		||||
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
 | 
			
		||||
            scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop);
 | 
			
		||||
            scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread";
 | 
			
		||||
            scriptLoadUnloadThread.IsBackground = true;
 | 
			
		||||
            scriptLoadUnloadThread.Priority = ThreadPriority.BelowNormal;
 | 
			
		||||
            scriptLoadUnloadThread.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~ScriptManager()
 | 
			
		||||
        {
 | 
			
		||||
            // Abort load/unload thread
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (scriptLoadUnloadThread != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (scriptLoadUnloadThread.IsAlive == true)
 | 
			
		||||
                    {
 | 
			
		||||
                        scriptLoadUnloadThread.Abort();
 | 
			
		||||
                        scriptLoadUnloadThread.Join();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Load / Unload scripts (Thread loop)
 | 
			
		||||
 | 
			
		||||
        private void ScriptLoadUnloadThreadLoop()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    if (LUQueue.Count == 0)
 | 
			
		||||
                        Thread.Sleep(scriptLoadUnloadThread_IdleSleepms);
 | 
			
		||||
                    if (LUQueue.Count > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        LUStruct item = LUQueue.Dequeue();
 | 
			
		||||
                        lock (startStopLock)        // Lock so we have only 1 thread working on loading/unloading of scripts
 | 
			
		||||
                        {
 | 
			
		||||
                            if (item.Action == LUType.Unload)
 | 
			
		||||
                            {
 | 
			
		||||
                                _StopScript(item.localID, item.itemID);
 | 
			
		||||
                            }
 | 
			
		||||
                            if (item.Action == LUType.Load)
 | 
			
		||||
                            {
 | 
			
		||||
                                _StartScript(item.localID, item.itemID, item.script);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (ThreadAbortException tae)
 | 
			
		||||
            {
 | 
			
		||||
                string a = tae.ToString();
 | 
			
		||||
                a = "";
 | 
			
		||||
                // Expected
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Helper functions
 | 
			
		||||
 | 
			
		||||
        private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
 | 
			
		||||
        {
 | 
			
		||||
            //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name);
 | 
			
		||||
            return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
        #region Start/Stop/Reset script
 | 
			
		||||
 | 
			
		||||
        private readonly Object startStopLock = new Object();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Fetches, loads and hooks up a script to an objects events
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="itemID"></param>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        public void StartScript(uint localID, LLUUID itemID, string Script)
 | 
			
		||||
        {
 | 
			
		||||
            LUStruct ls = new LUStruct();
 | 
			
		||||
            ls.localID = localID;
 | 
			
		||||
            ls.itemID = itemID;
 | 
			
		||||
            ls.script = Script;
 | 
			
		||||
            ls.Action = LUType.Load;
 | 
			
		||||
            LUQueue.Enqueue(ls);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Disables and unloads a script
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        /// <param name="itemID"></param>
 | 
			
		||||
        public void StopScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            LUStruct ls = new LUStruct();
 | 
			
		||||
            ls.localID = localID;
 | 
			
		||||
            ls.itemID = itemID;
 | 
			
		||||
            ls.Action = LUType.Unload;
 | 
			
		||||
            LUQueue.Enqueue(ls);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create a new instance of the compiler (reuse)
 | 
			
		||||
        //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler();
 | 
			
		||||
 | 
			
		||||
        public abstract void _StartScript(uint localID, LLUUID itemID, string Script);
 | 
			
		||||
 | 
			
		||||
        public abstract void _StopScript(uint localID, LLUUID itemID);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Perform event execution in script
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Execute a LL-event-function in Script
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID">Object the script is located in</param>
 | 
			
		||||
        /// <param name="itemID">Script ID</param>
 | 
			
		||||
        /// <param name="FunctionName">Name of function</param>
 | 
			
		||||
        /// <param name="args">Arguments to pass to function</param>
 | 
			
		||||
        internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, object[] args)
 | 
			
		||||
        {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
            Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName);
 | 
			
		||||
#endif
 | 
			
		||||
            // Execute a function in the script
 | 
			
		||||
            //m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
 | 
			
		||||
            //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
 | 
			
		||||
            IScript Script = GetScript(localID, itemID);
 | 
			
		||||
            if (Script == null)
 | 
			
		||||
                return;
 | 
			
		||||
#if DEBUG
 | 
			
		||||
            Console.WriteLine("ScriptEngine: Executing event: " + FunctionName);
 | 
			
		||||
#endif
 | 
			
		||||
            // Must be done in correct AppDomain, so leaving it up to the script itself
 | 
			
		||||
            Script.Exec.ExecuteEvent(FunctionName, args);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Internal functions to keep track of script
 | 
			
		||||
 | 
			
		||||
        public Dictionary<LLUUID, IScript>.KeyCollection GetScriptKeys(uint localID)
 | 
			
		||||
        {
 | 
			
		||||
            if (Scripts.ContainsKey(localID) == false)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            Dictionary<LLUUID, IScript> Obj;
 | 
			
		||||
            Scripts.TryGetValue(localID, out Obj);
 | 
			
		||||
 | 
			
		||||
            return Obj.Keys;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IScript GetScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            if (Scripts.ContainsKey(localID) == false)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            Dictionary<LLUUID, IScript> Obj;
 | 
			
		||||
            Scripts.TryGetValue(localID, out Obj);
 | 
			
		||||
            if (Obj.ContainsKey(itemID) == false)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            // Get script
 | 
			
		||||
            IScript Script;
 | 
			
		||||
            Obj.TryGetValue(itemID, out Script);
 | 
			
		||||
 | 
			
		||||
            return Script;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SetScript(uint localID, LLUUID itemID, IScript Script)
 | 
			
		||||
        {
 | 
			
		||||
            // Create object if it doesn't exist
 | 
			
		||||
            if (Scripts.ContainsKey(localID) == false)
 | 
			
		||||
            {
 | 
			
		||||
                Scripts.Add(localID, new Dictionary<LLUUID, IScript>());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Delete script if it exists
 | 
			
		||||
            Dictionary<LLUUID, IScript> Obj;
 | 
			
		||||
            Scripts.TryGetValue(localID, out Obj);
 | 
			
		||||
            if (Obj.ContainsKey(itemID) == true)
 | 
			
		||||
                Obj.Remove(itemID);
 | 
			
		||||
 | 
			
		||||
            // Add to object
 | 
			
		||||
            Obj.Add(itemID, Script);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RemoveScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Don't have that object?
 | 
			
		||||
            if (Scripts.ContainsKey(localID) == false)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            // Delete script if it exists
 | 
			
		||||
            Dictionary<LLUUID, IScript> Obj;
 | 
			
		||||
            Scripts.TryGetValue(localID, out Obj);
 | 
			
		||||
            if (Obj.ContainsKey(itemID) == true)
 | 
			
		||||
                Obj.Remove(itemID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public void ResetScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            string script = GetScript(localID, itemID).Source;
 | 
			
		||||
            StopScript(localID, itemID);
 | 
			
		||||
            StartScript(localID, itemID, script);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region Script serialization/deserialization
 | 
			
		||||
 | 
			
		||||
        public void GetSerializedScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Serialize the script and return it
 | 
			
		||||
            // Should not be a problem
 | 
			
		||||
            FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID);
 | 
			
		||||
            BinaryFormatter b = new BinaryFormatter();
 | 
			
		||||
            b.Serialize(fs, GetScript(localID, itemID));
 | 
			
		||||
            fs.Close();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void PutSerializedScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Deserialize the script and inject it into an AppDomain
 | 
			
		||||
 | 
			
		||||
            // How to inject into an AppDomain?
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
/*
 | 
			
		||||
* Copyright (c) Contributors, http://opensimulator.org/
 | 
			
		||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
 | 
			
		||||
*
 | 
			
		||||
* Redistribution and use in source and binary forms, with or without
 | 
			
		||||
* modification, are permitted provided that the following conditions are met:
 | 
			
		||||
*     * Redistributions of source code must retain the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
*     * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
*       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
*       documentation and/or other materials provided with the distribution.
 | 
			
		||||
*     * Neither the name of the OpenSim Project nor the
 | 
			
		||||
*       names of its contributors may be used to endorse or promote products
 | 
			
		||||
*       derived from this software without specific prior written permission.
 | 
			
		||||
*
 | 
			
		||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
 | 
			
		||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
 | 
			
		||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
* 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Runtime.Serialization.Formatters.Binary;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using libsecondlife;
 | 
			
		||||
using OpenSim.Framework;
 | 
			
		||||
using OpenSim.Region.Environment.Scenes;
 | 
			
		||||
using OpenSim.Region.ScriptEngine.Common;
 | 
			
		||||
 | 
			
		||||
namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Loads scripts
 | 
			
		||||
    /// Compiles them if necessary
 | 
			
		||||
    /// Execute functions for EventQueueManager (Sends them to script on other AppDomain for execution)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// 
 | 
			
		||||
 | 
			
		||||
    // This class is as close as you get to the script without being inside script class. It handles all the dirty work for other classes.
 | 
			
		||||
    // * Keeps track of running scripts
 | 
			
		||||
    // * Compiles script if necessary (through "Compiler")
 | 
			
		||||
    // * Loads script (through "AppDomainManager" called from for example "EventQueueManager")
 | 
			
		||||
    // * Executes functions inside script (called from for example "EventQueueManager" class)
 | 
			
		||||
    // * Unloads script (through "AppDomainManager" called from for example "EventQueueManager")
 | 
			
		||||
    // * Dedicated load/unload thread, and queues loading/unloading.
 | 
			
		||||
    //   This so that scripts starting or stopping will not slow down other theads or whole system.
 | 
			
		||||
    //
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public abstract class ScriptManager
 | 
			
		||||
    {
 | 
			
		||||
        #region Declares
 | 
			
		||||
 | 
			
		||||
        private Thread scriptLoadUnloadThread;
 | 
			
		||||
        private int scriptLoadUnloadThread_IdleSleepms = 100;
 | 
			
		||||
        private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Load/Unload structure
 | 
			
		||||
        private struct LUStruct
 | 
			
		||||
        {
 | 
			
		||||
            public uint localID;
 | 
			
		||||
            public LLUUID itemID;
 | 
			
		||||
            public string script;
 | 
			
		||||
            public LUType Action;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private enum LUType
 | 
			
		||||
        {
 | 
			
		||||
            Unknown = 0,
 | 
			
		||||
            Load = 1,
 | 
			
		||||
            Unload = 2
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Object<string, Script<string, script>>
 | 
			
		||||
        // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
 | 
			
		||||
        // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
 | 
			
		||||
        public Dictionary<uint, Dictionary<LLUUID, IScript>> Scripts =
 | 
			
		||||
            new Dictionary<uint, Dictionary<LLUUID, IScript>>();
 | 
			
		||||
 | 
			
		||||
        public Scene World
 | 
			
		||||
        {
 | 
			
		||||
            get { return m_scriptEngine.World; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Object init/shutdown
 | 
			
		||||
 | 
			
		||||
        public ScriptEngineBase.ScriptEngine m_scriptEngine;
 | 
			
		||||
 | 
			
		||||
        public ScriptManager(ScriptEngineBase.ScriptEngine scriptEngine)
 | 
			
		||||
        {
 | 
			
		||||
            m_scriptEngine = scriptEngine;
 | 
			
		||||
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
 | 
			
		||||
            scriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop);
 | 
			
		||||
            scriptLoadUnloadThread.Name = "ScriptLoadUnloadThread";
 | 
			
		||||
            scriptLoadUnloadThread.IsBackground = true;
 | 
			
		||||
            scriptLoadUnloadThread.Priority = ThreadPriority.BelowNormal;
 | 
			
		||||
            scriptLoadUnloadThread.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ~ScriptManager()
 | 
			
		||||
        {
 | 
			
		||||
            // Abort load/unload thread
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (scriptLoadUnloadThread != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (scriptLoadUnloadThread.IsAlive == true)
 | 
			
		||||
                    {
 | 
			
		||||
                        scriptLoadUnloadThread.Abort();
 | 
			
		||||
                        scriptLoadUnloadThread.Join();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Load / Unload scripts (Thread loop)
 | 
			
		||||
 | 
			
		||||
        private void ScriptLoadUnloadThreadLoop()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    if (LUQueue.Count == 0)
 | 
			
		||||
                        Thread.Sleep(scriptLoadUnloadThread_IdleSleepms);
 | 
			
		||||
                    if (LUQueue.Count > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        LUStruct item = LUQueue.Dequeue();
 | 
			
		||||
                        lock (startStopLock)        // Lock so we have only 1 thread working on loading/unloading of scripts
 | 
			
		||||
                        {
 | 
			
		||||
                            if (item.Action == LUType.Unload)
 | 
			
		||||
                            {
 | 
			
		||||
                                _StopScript(item.localID, item.itemID);
 | 
			
		||||
                            }
 | 
			
		||||
                            if (item.Action == LUType.Load)
 | 
			
		||||
                            {
 | 
			
		||||
                                _StartScript(item.localID, item.itemID, item.script);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (ThreadAbortException tae)
 | 
			
		||||
            {
 | 
			
		||||
                string a = tae.ToString();
 | 
			
		||||
                a = "";
 | 
			
		||||
                // Expected
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Helper functions
 | 
			
		||||
 | 
			
		||||
        private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
 | 
			
		||||
        {
 | 
			
		||||
            //Console.WriteLine("ScriptManager.CurrentDomain_AssemblyResolve: " + args.Name);
 | 
			
		||||
            return Assembly.GetExecutingAssembly().FullName == args.Name ? Assembly.GetExecutingAssembly() : null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
        #region Start/Stop/Reset script
 | 
			
		||||
 | 
			
		||||
        private readonly Object startStopLock = new Object();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Fetches, loads and hooks up a script to an objects events
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="itemID"></param>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        public void StartScript(uint localID, LLUUID itemID, string Script)
 | 
			
		||||
        {
 | 
			
		||||
            LUStruct ls = new LUStruct();
 | 
			
		||||
            ls.localID = localID;
 | 
			
		||||
            ls.itemID = itemID;
 | 
			
		||||
            ls.script = Script;
 | 
			
		||||
            ls.Action = LUType.Load;
 | 
			
		||||
            LUQueue.Enqueue(ls);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Disables and unloads a script
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID"></param>
 | 
			
		||||
        /// <param name="itemID"></param>
 | 
			
		||||
        public void StopScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            LUStruct ls = new LUStruct();
 | 
			
		||||
            ls.localID = localID;
 | 
			
		||||
            ls.itemID = itemID;
 | 
			
		||||
            ls.Action = LUType.Unload;
 | 
			
		||||
            LUQueue.Enqueue(ls);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create a new instance of the compiler (reuse)
 | 
			
		||||
        //private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler();
 | 
			
		||||
 | 
			
		||||
        public abstract void _StartScript(uint localID, LLUUID itemID, string Script);
 | 
			
		||||
 | 
			
		||||
        public abstract void _StopScript(uint localID, LLUUID itemID);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Perform event execution in script
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Execute a LL-event-function in Script
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="localID">Object the script is located in</param>
 | 
			
		||||
        /// <param name="itemID">Script ID</param>
 | 
			
		||||
        /// <param name="FunctionName">Name of function</param>
 | 
			
		||||
        /// <param name="args">Arguments to pass to function</param>
 | 
			
		||||
        internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, object[] args)
 | 
			
		||||
        {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
            Console.WriteLine("ScriptEngine: Inside ExecuteEvent for event " + FunctionName);
 | 
			
		||||
#endif
 | 
			
		||||
            // Execute a function in the script
 | 
			
		||||
            //m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
 | 
			
		||||
            //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
 | 
			
		||||
            IScript Script = GetScript(localID, itemID);
 | 
			
		||||
            if (Script == null)
 | 
			
		||||
                return;
 | 
			
		||||
#if DEBUG
 | 
			
		||||
            Console.WriteLine("ScriptEngine: Executing event: " + FunctionName);
 | 
			
		||||
#endif
 | 
			
		||||
            // Must be done in correct AppDomain, so leaving it up to the script itself
 | 
			
		||||
            Script.Exec.ExecuteEvent(FunctionName, args);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Internal functions to keep track of script
 | 
			
		||||
 | 
			
		||||
        public Dictionary<LLUUID, IScript>.KeyCollection GetScriptKeys(uint localID)
 | 
			
		||||
        {
 | 
			
		||||
            if (Scripts.ContainsKey(localID) == false)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            Dictionary<LLUUID, IScript> Obj;
 | 
			
		||||
            Scripts.TryGetValue(localID, out Obj);
 | 
			
		||||
 | 
			
		||||
            return Obj.Keys;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IScript GetScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            if (Scripts.ContainsKey(localID) == false)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            Dictionary<LLUUID, IScript> Obj;
 | 
			
		||||
            Scripts.TryGetValue(localID, out Obj);
 | 
			
		||||
            if (Obj.ContainsKey(itemID) == false)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            // Get script
 | 
			
		||||
            IScript Script;
 | 
			
		||||
            Obj.TryGetValue(itemID, out Script);
 | 
			
		||||
 | 
			
		||||
            return Script;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SetScript(uint localID, LLUUID itemID, IScript Script)
 | 
			
		||||
        {
 | 
			
		||||
            // Create object if it doesn't exist
 | 
			
		||||
            if (Scripts.ContainsKey(localID) == false)
 | 
			
		||||
            {
 | 
			
		||||
                Scripts.Add(localID, new Dictionary<LLUUID, IScript>());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Delete script if it exists
 | 
			
		||||
            Dictionary<LLUUID, IScript> Obj;
 | 
			
		||||
            Scripts.TryGetValue(localID, out Obj);
 | 
			
		||||
            if (Obj.ContainsKey(itemID) == true)
 | 
			
		||||
                Obj.Remove(itemID);
 | 
			
		||||
 | 
			
		||||
            // Add to object
 | 
			
		||||
            Obj.Add(itemID, Script);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RemoveScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Don't have that object?
 | 
			
		||||
            if (Scripts.ContainsKey(localID) == false)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            // Delete script if it exists
 | 
			
		||||
            Dictionary<LLUUID, IScript> Obj;
 | 
			
		||||
            Scripts.TryGetValue(localID, out Obj);
 | 
			
		||||
            if (Obj.ContainsKey(itemID) == true)
 | 
			
		||||
                Obj.Remove(itemID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public void ResetScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            string script = GetScript(localID, itemID).Source;
 | 
			
		||||
            StopScript(localID, itemID);
 | 
			
		||||
            StartScript(localID, itemID, script);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region Script serialization/deserialization
 | 
			
		||||
 | 
			
		||||
        public void GetSerializedScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Serialize the script and return it
 | 
			
		||||
            // Should not be a problem
 | 
			
		||||
            FileStream fs = File.Create("SERIALIZED_SCRIPT_" + itemID);
 | 
			
		||||
            BinaryFormatter b = new BinaryFormatter();
 | 
			
		||||
            b.Serialize(fs, GetScript(localID, itemID));
 | 
			
		||||
            fs.Close();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void PutSerializedScript(uint localID, LLUUID itemID)
 | 
			
		||||
        {
 | 
			
		||||
            // Deserialize the script and inject it into an AppDomain
 | 
			
		||||
 | 
			
		||||
            // How to inject into an AppDomain?
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue