Ejemplo n.º 1
0
        /// <summary>
        ///     This starts the script and sets up the variables.
        /// </summary>
        /// <returns></returns>
        public bool Start(LUStruct startInfo)
        {
            bool reupload = startInfo.Action == LUType.Reupload;
            DateTime StartTime = DateTime.Now.ToUniversalTime();
            Running = true;
            Suspended = false;

            //Clear out the removing of events for this script.
            IgnoreNew = false;
            Interlocked.Increment(ref VersionID);

            //Reset this
            StartedFromSavedState = false;

            //Clear out previous errors if they were not cleaned up
            m_ScriptEngine.ScriptErrorReporter.RemoveError(ItemID);

            //Find the inventory item
            Part.TaskInventory.TryGetValue(ItemID, out InventoryItem);

            if (InventoryItem == null)
            {
                MainConsole.Instance.Warn("[WDNE]: Could not find inventory item for script " + ItemID + ", part" +
                                          Part.Name + "@" +
                                          Part.AbsolutePosition);
                return false;
            }

            //Try to see if this was rezzed from someone's inventory
            UserInventoryItemID = Part.FromUserInventoryItemID;

            //Try to find the avatar who started this.
            IScenePresence presence = World.GetScenePresence(Part.OwnerID);


            if (startInfo.ClearStateSaves)
                m_ScriptEngine.StateSave.DeleteFrom(this);
            //Now that the initial loading is complete,
            // we need to find the state save and start loading the info from it
            StateSave LastStateSave = m_ScriptEngine.StateSave.FindScriptStateSave(this);
            if (!reupload && Loading && LastStateSave != null)
            {
                //Deserialize the most important pieces first
                Source = LastStateSave.Source;
            }
            if (string.IsNullOrEmpty(Source))
            {
                byte[] asset = Part.ParentEntity.Scene.AssetService.GetData(InventoryItem.AssetID.ToString());
                if (null == asset)
                {
                    MainConsole.Instance.ErrorFormat(
                        "[ScriptData]: " +
                        "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
                        InventoryItem.Name, InventoryItem.ItemID, Part.AbsolutePosition,
                        Part.ParentEntity.Scene.RegionInfo.RegionName, InventoryItem.AssetID);
                    ScriptEngine.ScriptProtection.RemoveScript(this);
                    return false;
                }
                Source = Utils.BytesToString(asset);
            }
            if (string.IsNullOrEmpty(Source))
            {
                MainConsole.Instance.ErrorFormat(
                    "[ScriptData]: " +
                    "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
                    InventoryItem.Name, InventoryItem.ItemID, Part.AbsolutePosition,
                    Part.ParentEntity.Scene.RegionInfo.RegionName, InventoryItem.AssetID);
                ScriptEngine.ScriptProtection.RemoveScript(this);
                return false;
            }

            #region HTML Reader

            if (ScriptEngine.ScriptProtection.AllowHTMLLinking)
            {
                //Read the URL and load it.
                if (Source.Contains("#IncludeHTML "))
                {
                    string URL = "";
                    int line = Source.IndexOf ("#IncludeHTML ", StringComparison.Ordinal);
                    URL = Source.Remove(0, line);
                    URL = URL.Replace("#IncludeHTML ", "");
                    URL = URL.Split('\n')[0];
                    string webSite = Utilities.ReadExternalWebsite(URL);
                    Source = Source.Replace("#IncludeHTML " + URL, webSite);
                }
            }
            else
            {
                //Remove the line then
                if (Source.Contains("#IncludeHTML "))
                {
                    string URL = "";
                    int line = Source.IndexOf ("#IncludeHTML ", StringComparison.Ordinal);
                    URL = Source.Remove(0, line);
                    URL = URL.Replace("#IncludeHTML ", "");
                    URL = URL.Split('\n')[0];
                    Source = Source.Replace("#IncludeHTML " + URL, "");
                }
            }

            #endregion

            //Find the default state save
            DefaultState = m_ScriptEngine.Compiler.FindDefaultStateForScript(Source);
            State = DefaultState;

            //If the saved state exists, if it isn't a reupload (something changed), and if the assembly exists, load the state save
            if (!reupload && Loading && LastStateSave != null
                && File.Exists(LastStateSave.AssemblyName))
            {
                //Retrive the previous assembly
                AssemblyName = LastStateSave.AssemblyName;
            }
            else
            {
                Compiled = false;
                //if (!reupload && Loading && LastStateSave != null && !LastStateSave.Compiled)
                //    return false;//If we're trying to start up and we failed before, just give up
                if (reupload)
                {
                    LastStateSave = null;
                    //Close the previous script
                    CloseAndDispose(false); //We don't want to back it up
                    Interlocked.Increment(ref VersionID);
                    m_ScriptEngine.MaintenanceThread.SetEventSchSetIgnoreNew(this, false); // accept new events
                }

                //Try to find a previously compiled script in this instance
                string PreviouslyCompiledAssemblyName =
                    ScriptEngine.ScriptProtection.TryGetPreviouslyCompiledScript(Source);
                if (PreviouslyCompiledAssemblyName != null)
                    //Already exists in this instance, so we do not need to check whether it exists
                    AssemblyName = PreviouslyCompiledAssemblyName;
                else
                {
                    try
                    {
                        m_ScriptEngine.Compiler.PerformScriptCompile(Source, Part.OwnerID, out AssemblyName);

                        #region Errors and Warnings

                        #region Errors

                        string[] compileerrors = m_ScriptEngine.Compiler.GetErrors();

                        if (compileerrors.Length != 0)
                        {
                            string error = string.Empty;
                            foreach (string compileerror in compileerrors)
                            {
                                error += compileerror;
                            }
                            DisplayUserNotification(error, "compiling", reupload, true);
                            //It might have failed, but we still need to add it so that we can reuse this script data class later
                            ScriptEngine.ScriptProtection.AddNewScript(this);
                            m_ScriptEngine.StateSave.SaveStateTo(this, true);
                            return false;
                        }

                        #endregion

                        #region Warnings

                        if (m_ScriptEngine.ShowWarnings)
                        {
                            string[] compilewarnings = m_ScriptEngine.Compiler.GetWarnings();

                            if (compilewarnings != null && compilewarnings.Length != 0)
                            {
                                string error = string.Empty;
                                foreach (string compileerror in compilewarnings)
                                {
                                    error += compileerror;
                                }
                                DisplayUserNotification(error, "compiling", reupload, false);
                                //It might have failed, but we still need to add it so that we can reuse this script data class later
                                ScriptEngine.ScriptProtection.AddNewScript(this);
                                return false;
                            }
                        }

                        #endregion

                        #endregion
                    }
                    catch (Exception ex)
                    {
                        //LEAVE IT AS ToString() SO THAT WE GET THE STACK TRACE TOO
                        DisplayUserNotification(ex.ToString(), "(exception) compiling", reupload, true);
                        //It might have failed, but we still need to add it so that we can reuse this script data class later
                        ScriptEngine.ScriptProtection.AddNewScript(this);
                        return false;
                    }
                }
            }

            #if SHOWDEBUG
                MainConsole.Instance.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Stage 1 compile: " +
                                           (DateTime.Now.ToUniversalTime() - StartTime).TotalSeconds);
            #endif

            //Create the app domain if needed.
            try
            {
                Script = m_ScriptEngine.AppDomainManager.LoadScript(AssemblyName, "Script.ScriptClass", out AppDomain);
                if (Script == null)
                    return false;
                
                m_ScriptEngine.Compiler.FinishCompile(this, Script);
                //Add now so that we don't add it too early and give it the possibility to fail
                ScriptEngine.ScriptProtection.AddPreviouslyCompiled(Source, this);
            }
            catch (FileNotFoundException) // Not valid!!!
            {
                MainConsole.Instance.Error("[" + m_ScriptEngine.ScriptEngineName +
                                           "]: File not found in app domain creation. Corrupt state save! " +
                                           AssemblyName);
                ScriptEngine.ScriptProtection.RemovePreviouslyCompiled(Source);
                return Start(startInfo); // Lets restart the script if this happens
            }
            catch (Exception ex)
            {
                DisplayUserNotification(ex.ToString(), "app domain creation", reupload, true);
                //It might have failed, but we still need to add it so that we can reuse this script data class later
                ScriptEngine.ScriptProtection.AddNewScript(this);
                return false;
            }
            Compiled = true; //We compiled successfully

            //ILease lease = (ILease)RemotingServices.GetLifetimeService(Script as MarshalByRefObject);
            //if (lease != null) //Its null if it is all running in the same app domain
            //    lease.Register(Script.Sponsor);

            //If its a reupload, an avatar is waiting for the script errors
            if (reupload)
                m_ScriptEngine.ScriptErrorReporter.AddError(ItemID, new ArrayList(new[] {"SUCCESSFULL"}));

            #if SHOWDEBUG
                MainConsole.Instance.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Stage 2 compile: " +
                                           (DateTime.Now.ToUniversalTime() - StartTime).TotalSeconds);
            #endif

            SetApis();

            //Now do the full state save finding now that we have an app domain.
            if (LastStateSave != null)
            {
                string assy = AssemblyName;
                // don't restore the assembly name, the one we have is right (if re-compiled or not)
                m_ScriptEngine.StateSave.Deserialize(this, LastStateSave);
                AssemblyName = assy;
                if (string.IsNullOrEmpty(State) && DefaultState != State)
                    //Sometimes, "" is a valid state for other script languages
                {
                    MainConsole.Instance.Warn("Resetting broken script save state\n" +
                        "                :  "+InventoryItem.Name+":"+Part.Name + " @ " +Part.AbsolutePosition +
                    "\n                     in region " + Part.ParentEntity.Scene.RegionInfo.RegionName);

                    State = DefaultState;
                    m_ScriptEngine.StateSave.DeleteFrom(Part, LastStateSave.ItemID);
                    m_ScriptEngine.StateSave.SaveStateTo(this, true);
                }
                else
                {
                    // we get new rez events on sim restart, too
                    // but if there is state, then we fire the change
                    // event
                    StartedFromSavedState = true;
                }

                // ItemID changes sometimes (not sure why, but observed it)
                // If so we want to clear out the old save state,
                // which would otherwise have hung around in the object forever
                if (LastStateSave.ItemID != ItemID)
                {
                    m_ScriptEngine.StateSave.DeleteFrom(Part, LastStateSave.ItemID);
                    m_ScriptEngine.StateSave.SaveStateTo(this, true);
                }
            }
            else
            {
                //Make a new state save now
                m_ScriptEngine.StateSave.SaveStateTo(this, true);
            }

            //Set the event flags
            Part.SetScriptEvents(ItemID, Script.GetStateEventFlags(State));

            // Add it to our script memstruct so it can be found by other scripts
            ScriptEngine.ScriptProtection.AddNewScript(this);

            //All done, compiled successfully
            Loading = false;

            if (MainConsole.Instance.IsDebugEnabled)
            {
                TimeSpan time = (DateTime.Now.ToUniversalTime() - StartTime);

                MainConsole.Instance.Debug("[" + m_ScriptEngine.ScriptEngineName +
                                           "]: Started Script " + InventoryItem.Name +
                                           " in object " + Part.Name + "@" +
                                           Part.ParentEntity.RootChild.AbsolutePosition +
                                           (presence != null ? " by " + presence.Name : "") +
                                           " in region " + Part.ParentEntity.Scene.RegionInfo.RegionName +
                                           " in " + time.TotalSeconds + " seconds.");
            }
            return true;
        }
        public void StartScripts(LUStruct[] items)
        {
            List<LUStruct> NeedsFired = new List<LUStruct>();
            foreach (LUStruct item in items)
            {
                if (m_ScriptEngine.ConsoleDisabled || m_ScriptEngine.Disabled || m_ScriptEngine.Scene == null ||
                    !m_ScriptEngine.Scene.ShouldRunHeartbeat)
                    break;

                if (item.Action == LUType.Unload)
                {
                    //Close
                    item.ID.CloseAndDispose(true);
                }
                else if (item.Action == LUType.Load ||
                         item.Action == LUType.Reupload)
                {
                    try
                    {
                        //Start
                        if (item.ID.Start(item))
                            NeedsFired.Add(item);
                    }
                    catch (Exception ex)
                    {
                        MainConsole.Instance.Error("[" + m_ScriptEngine.ScriptEngineName + "]: LEAKED COMPILE ERROR: " +
                                                   ex);
                    }
                }
            }
            foreach (LUStruct item in NeedsFired)
            {
                //Fire the events afterward so that they all start at the same time
                item.ID.FireEvents();
            }
        }
 public void AddScriptChange(LUStruct[] items, LoadPriority priority)
 {
     if (RunInMainProcessingThread)
         StartScripts(items);
     else
     {
         LUQueue.Add(items, priority);
         if (!ScriptChangeIsRunning)
             StartThread("Change");
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        ///     This starts the script and sets up the variables.
        /// </summary>
        /// <returns></returns>
        public bool Start(LUStruct startInfo)
        {
            bool     reupload  = startInfo.Action == LUType.Reupload;
            DateTime StartTime = DateTime.Now.ToUniversalTime();

            Running   = true;
            Suspended = false;

            //Clear out the removing of events for this script.
            IgnoreNew = false;
            Interlocked.Increment(ref VersionID);

            //Reset this
            StartedFromSavedState = false;

            //Clear out previous errors if they were not cleaned up
            m_ScriptEngine.ScriptErrorReporter.RemoveError(ItemID);

            //Find the inventory item
            Part.TaskInventory.TryGetValue(ItemID, out InventoryItem);

            if (InventoryItem == null)
            {
                MainConsole.Instance.Warn("[WDNE]: Could not find inventory item for script " + ItemID + ", part" +
                                          Part.Name + "@" +
                                          Part.AbsolutePosition);
                return(false);
            }

            //Try to see if this was rezzed from someone's inventory
            UserInventoryItemID = Part.FromUserInventoryItemID;

            //Try to find the avatar who started this.
            IScenePresence presence = World.GetScenePresence(Part.OwnerID);


            if (startInfo.ClearStateSaves)
            {
                m_ScriptEngine.StateSave.DeleteFrom(this);
            }
            //Now that the initial loading is complete,
            // we need to find the state save and start loading the info from it
            StateSave LastStateSave = m_ScriptEngine.StateSave.FindScriptStateSave(this);

            if (!reupload && Loading && LastStateSave != null)
            {
                //Deserialize the most important pieces first
                Source = LastStateSave.Source;
            }
            if (string.IsNullOrEmpty(Source))
            {
                byte[] asset = Part.ParentEntity.Scene.AssetService.GetData(InventoryItem.AssetID.ToString());
                if (null == asset)
                {
                    MainConsole.Instance.ErrorFormat(
                        "[ScriptData]: " +
                        "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
                        InventoryItem.Name, InventoryItem.ItemID, Part.AbsolutePosition,
                        Part.ParentEntity.Scene.RegionInfo.RegionName, InventoryItem.AssetID);
                    ScriptEngine.ScriptProtection.RemoveScript(this);
                    return(false);
                }
                Source = Utils.BytesToString(asset);
            }
            if (string.IsNullOrEmpty(Source))
            {
                MainConsole.Instance.ErrorFormat(
                    "[ScriptData]: " +
                    "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
                    InventoryItem.Name, InventoryItem.ItemID, Part.AbsolutePosition,
                    Part.ParentEntity.Scene.RegionInfo.RegionName, InventoryItem.AssetID);
                ScriptEngine.ScriptProtection.RemoveScript(this);
                return(false);
            }

            #region HTML Reader

            if (ScriptEngine.ScriptProtection.AllowHTMLLinking)
            {
                //Read the URL and load it.
                if (Source.Contains("#IncludeHTML "))
                {
                    string URL  = "";
                    int    line = Source.IndexOf("#IncludeHTML ", StringComparison.Ordinal);
                    URL = Source.Remove(0, line);
                    URL = URL.Replace("#IncludeHTML ", "");
                    URL = URL.Split('\n')[0];
                    string webSite = Utilities.ReadExternalWebsite(URL);
                    Source = Source.Replace("#IncludeHTML " + URL, webSite);
                }
            }
            else
            {
                //Remove the line then
                if (Source.Contains("#IncludeHTML "))
                {
                    string URL  = "";
                    int    line = Source.IndexOf("#IncludeHTML ", StringComparison.Ordinal);
                    URL    = Source.Remove(0, line);
                    URL    = URL.Replace("#IncludeHTML ", "");
                    URL    = URL.Split('\n')[0];
                    Source = Source.Replace("#IncludeHTML " + URL, "");
                }
            }

            #endregion

            //Find the default state save
            DefaultState = m_ScriptEngine.Compiler.FindDefaultStateForScript(Source);
            State        = DefaultState;

            //If the saved state exists, if it isn't a reupload (something changed), and if the assembly exists, load the state save
            if (!reupload && Loading && LastStateSave != null &&
                File.Exists(LastStateSave.AssemblyName))
            {
                //Retrive the previous assembly
                AssemblyName = LastStateSave.AssemblyName;
            }
            else
            {
                Compiled = false;
                //if (!reupload && Loading && LastStateSave != null && !LastStateSave.Compiled)
                //    return false;//If we're trying to start up and we failed before, just give up
                if (reupload)
                {
                    LastStateSave = null;
                    //Close the previous script
                    CloseAndDispose(false);                                                //We don't want to back it up
                    Interlocked.Increment(ref VersionID);
                    m_ScriptEngine.MaintenanceThread.SetEventSchSetIgnoreNew(this, false); // accept new events
                }

                //Try to find a previously compiled script in this instance
                string PreviouslyCompiledAssemblyName =
                    ScriptEngine.ScriptProtection.TryGetPreviouslyCompiledScript(Source);
                if (PreviouslyCompiledAssemblyName != null)
                {
                    //Already exists in this instance, so we do not need to check whether it exists
                    AssemblyName = PreviouslyCompiledAssemblyName;
                }
                else
                {
                    try
                    {
                        m_ScriptEngine.Compiler.PerformScriptCompile(Source, Part.OwnerID, out AssemblyName);

                        #region Errors and Warnings

                        #region Errors

                        string[] compileerrors = m_ScriptEngine.Compiler.GetErrors();

                        if (compileerrors.Length != 0)
                        {
                            string error = string.Empty;
                            foreach (string compileerror in compileerrors)
                            {
                                error += compileerror;
                            }
                            DisplayUserNotification(error, "compiling", reupload, true);
                            //It might have failed, but we still need to add it so that we can reuse this script data class later
                            ScriptEngine.ScriptProtection.AddNewScript(this);
                            m_ScriptEngine.StateSave.SaveStateTo(this, true);
                            return(false);
                        }

                        #endregion

                        #region Warnings

                        if (m_ScriptEngine.ShowWarnings)
                        {
                            string[] compilewarnings = m_ScriptEngine.Compiler.GetWarnings();

                            if (compilewarnings != null && compilewarnings.Length != 0)
                            {
                                string error = string.Empty;
                                foreach (string compileerror in compilewarnings)
                                {
                                    error += compileerror;
                                }
                                DisplayUserNotification(error, "compiling", reupload, false);
                                //It might have failed, but we still need to add it so that we can reuse this script data class later
                                ScriptEngine.ScriptProtection.AddNewScript(this);
                                return(false);
                            }
                        }

                        #endregion

                        #endregion
                    }
                    catch (Exception ex)
                    {
                        //LEAVE IT AS ToString() SO THAT WE GET THE STACK TRACE TOO
                        DisplayUserNotification(ex.ToString(), "(exception) compiling", reupload, true);
                        //It might have failed, but we still need to add it so that we can reuse this script data class later
                        ScriptEngine.ScriptProtection.AddNewScript(this);
                        return(false);
                    }
                }
            }

            #if SHOWDEBUG
            MainConsole.Instance.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Stage 1 compile: " +
                                       (DateTime.Now.ToUniversalTime() - StartTime).TotalSeconds);
            #endif

            //Create the app domain if needed.
            try
            {
                Script = m_ScriptEngine.AppDomainManager.LoadScript(AssemblyName, "Script.ScriptClass", out AppDomain);
                if (Script == null)
                {
                    return(false);
                }

                m_ScriptEngine.Compiler.FinishCompile(this, Script);
                //Add now so that we don't add it too early and give it the possibility to fail
                ScriptEngine.ScriptProtection.AddPreviouslyCompiled(Source, this);
            }
            catch (FileNotFoundException) // Not valid!!!
            {
                MainConsole.Instance.Error("[" + m_ScriptEngine.ScriptEngineName +
                                           "]: File not found in app domain creation. Corrupt state save! " +
                                           AssemblyName);
                ScriptEngine.ScriptProtection.RemovePreviouslyCompiled(Source);
                return(Start(startInfo)); // Lets restart the script if this happens
            }
            catch (Exception ex)
            {
                DisplayUserNotification(ex.ToString(), "app domain creation", reupload, true);
                //It might have failed, but we still need to add it so that we can reuse this script data class later
                ScriptEngine.ScriptProtection.AddNewScript(this);
                return(false);
            }
            Compiled = true; //We compiled successfully

            //ILease lease = (ILease)RemotingServices.GetLifetimeService(Script as MarshalByRefObject);
            //if (lease != null) //Its null if it is all running in the same app domain
            //    lease.Register(Script.Sponsor);

            //If its a reupload, an avatar is waiting for the script errors
            if (reupload)
            {
                m_ScriptEngine.ScriptErrorReporter.AddError(ItemID, new ArrayList(new[] { "SUCCESSFULL" }));
            }

            #if SHOWDEBUG
            MainConsole.Instance.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Stage 2 compile: " +
                                       (DateTime.Now.ToUniversalTime() - StartTime).TotalSeconds);
            #endif

            SetApis();

            //Now do the full state save finding now that we have an app domain.
            if (LastStateSave != null)
            {
                string assy = AssemblyName;
                // don't restore the assembly name, the one we have is right (if re-compiled or not)
                m_ScriptEngine.StateSave.Deserialize(this, LastStateSave);
                AssemblyName = assy;
                if (string.IsNullOrEmpty(State) && DefaultState != State)
                //Sometimes, "" is a valid state for other script languages
                {
                    MainConsole.Instance.Warn("Resetting broken script save state\n" +
                                              "                :  " + InventoryItem.Name + ":" + Part.Name + " @ " + Part.AbsolutePosition +
                                              "\n                     in region " + Part.ParentEntity.Scene.RegionInfo.RegionName);

                    State = DefaultState;
                    m_ScriptEngine.StateSave.DeleteFrom(Part, LastStateSave.ItemID);
                    m_ScriptEngine.StateSave.SaveStateTo(this, true);
                }
                else
                {
                    // we get new rez events on sim restart, too
                    // but if there is state, then we fire the change
                    // event
                    StartedFromSavedState = true;
                }

                // ItemID changes sometimes (not sure why, but observed it)
                // If so we want to clear out the old save state,
                // which would otherwise have hung around in the object forever
                if (LastStateSave.ItemID != ItemID)
                {
                    m_ScriptEngine.StateSave.DeleteFrom(Part, LastStateSave.ItemID);
                    m_ScriptEngine.StateSave.SaveStateTo(this, true);
                }
            }
            else
            {
                //Make a new state save now
                m_ScriptEngine.StateSave.SaveStateTo(this, true);
            }

            //Set the event flags
            Part.SetScriptEvents(ItemID, Script.GetStateEventFlags(State));

            // Add it to our script memstruct so it can be found by other scripts
            ScriptEngine.ScriptProtection.AddNewScript(this);

            //All done, compiled successfully
            Loading = false;

            if (MainConsole.Instance.IsDebugEnabled)
            {
                TimeSpan time = (DateTime.Now.ToUniversalTime() - StartTime);

                MainConsole.Instance.Debug("[" + m_ScriptEngine.ScriptEngineName +
                                           "]: Started Script " + InventoryItem.Name +
                                           " in object " + Part.Name + "@" +
                                           Part.ParentEntity.RootChild.AbsolutePosition +
                                           (presence != null ? " by " + presence.Name : "") +
                                           " in region " + Part.ParentEntity.Scene.RegionInfo.RegionName +
                                           " in " + time.TotalSeconds + " seconds.");
            }
            return(true);
        }