/// <summary>
        ///     Copys the given processes data to this process.
        /// </summary>
        /// <param name="vm">Virtual machine this oricess us associated with.</param>
        /// <param name="process">Process to recieve data from.</param>
        public ScriptProcess(VirtualMachine vm, ScriptProcess process)
        {
            HighPreformanceTimer timer = new HighPreformanceTimer();

            // Store virtual machine for layer use.
            _virtualMachine = vm;

            // Load the given script into this process.
            process.CopyTo(this);

            // Create a default thread that should run this process.
            ScriptThread newThread = new ScriptThread(this);

            // Attach console commands / exported command to this thread.
            // TODO: What if they already exist?
            foreach (Symbol symbol in _symbolList)
                if (symbol != null && symbol.Type == SymbolType.Function)
                {
                    if (((FunctionSymbol)symbol).IsConsole == true)
                        new ScriptConsoleCommand((FunctionSymbol)symbol, newThread);
                    else if (((FunctionSymbol)symbol).IsExport == true)
                        new ScriptExportFunction((FunctionSymbol)symbol, newThread);
                    else if (((FunctionSymbol)symbol).IsImport == true)
                    {
                        // Find the functions parameter types.
                        DataTypeValue[] parameterTypes = new DataTypeValue[((FunctionSymbol)symbol).ParameterCount];
                        for (int i = 0; i < ((FunctionSymbol)symbol).ParameterCount; i++)
                            parameterTypes[(((FunctionSymbol)symbol).ParameterCount - 1) - i] = ((VariableSymbol)symbol.Symbols[i]).DataType;

                        ((FunctionSymbol)symbol).NativeFunction = _virtualMachine.FindNativeFunction(symbol.Identifier, parameterTypes);
                    }
                }
        }
        /// <summary>
        ///		Loads a new script and creates a process out of it, then associates it
        ///		with this virtual machine.
        /// </summary>
        /// <param name="url">Url of file this script is in.</param>
        /// <param name="cache">If set to true this scripts byte code will be cached for quick loading.</param>
        public ScriptProcess LoadScript(object url, bool cache)
        {
            DebugLogger.WriteLog("Loading script into virtual machine from " + url);

            HighPreformanceTimer timer = new HighPreformanceTimer();

            if (Resources.ResourceManager.ResourceIsCached(url.ToString()))
            {
                ScriptProcess oldProcess = (ScriptProcess)Resources.ResourceManager.RetrieveResource(url.ToString());

                // Create process and hand loading over to it.
                ScriptProcess process = new ScriptProcess(this, (ScriptProcess)oldProcess);
                process.Url = url as string;
                _processes.Add(process);

                DebugLogger.WriteLog("Loaded script from cache in "+timer.DurationMillisecond+".");

                return process;
            }

            // Open a stream so we can read in the script.
            Stream stream = StreamFactory.RequestStream(url, StreamMode.Open);
            if (stream == null) return null;
            BinaryReader reader = new BinaryReader(stream);

            // Check if this script is already compiled or not.
            if (reader.ReadByte() == 'C' && reader.ReadByte() == 'R' && reader.ReadByte() == 'X')
            {
                // Clean up our file handle.
                reader.Close();
                stream.Close();

                // Create process and hand loading over to it.
                ScriptProcess process = new ScriptProcess(this, url);
                process.Url = url as string;
                _processes.Add(process);

                if (cache == true) Resources.ResourceManager.CacheResource(url.ToString(), process);

                DebugLogger.WriteLog("Script loaded in " + timer.DurationMillisecond + ".");
                return process;
            }
            else
            {
                // Clean up our file handle.
                reader.Close();

                // Compiler script to byte code.
                ScriptCompiler compiler = new ScriptCompiler();
                if (compiler.Compile(url) > 0)
                {
                    bool serious = false;
                    foreach (CompileError error in compiler.ErrorList)
                        if (error.AlertLevel == ErrorAlertLevel.Error || error.AlertLevel == ErrorAlertLevel.FatalError)
                            serious = true;

                    if (serious == true)
                    {
                        DebugLogger.WriteLog(compiler.ErrorList.Count + " error(s) occured while compiling script from " + url.ToString() + ".");
                        foreach (CompileError error in compiler.ErrorList)
                            DebugLogger.WriteLog("\t" + error.ToString());
                        return null;
                    }
                }

                // Create a memory stream and dump the byte code into it.
                Stream memoryStream = new MemoryStream();
                if (memoryStream == null) return null;
                BinaryWriter memoryWriter = new BinaryWriter(memoryStream);
                BinaryReader memoryReader = new BinaryReader(memoryStream);

                compiler.DumpExecutableFile(memoryWriter);

                // Create process and hand loading over to it.
                memoryStream.Position = 0;
                ScriptProcess process = new ScriptProcess(this, memoryReader);
                process.Url = url as string;
                _processes.Add(process);

                memoryReader.Close();
                memoryWriter.Close();
                memoryStream.Close();
                stream.Close();

                if (cache == true) Resources.ResourceManager.CacheResource(url.ToString(), process);
                DebugLogger.WriteLog("Script loaded in " + timer.DurationMillisecond + ".");
                return process;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        ///		Called by the base engine class when its safe to update and render the scene.
        /// </summary>
        protected override void Update()
        {
            // Ignore everything else if we are not running a game.
            if (_gameName == "")
            {
                return;
            }

            //System.Console.WriteLine("Collective Time("+EntityNode.CollectiveCalls+" calls): "+EntityNode.CollectiveTime);
            //EntityNode.CollectiveTime = 0.0f;
            //EntityNode.CollectiveCalls = 0;
            //EntityNode.CollectiveTimer.Restart();

            // Time to load a map?
            if (_mapLoadPending == true)
            {
                // Pump out a MapFinish event.
                EventManager.FireEvent(new Event("map_finish", this, null));

                // Allow the processes some time to be notified of closing events.
                //EventManager.ProcessEvents();
                //ProcessManager.RunProcesses(1);

                // Tell the scripts that we are now loading the new map (so they can show a loadings screen).
                _gameScriptProcess.Process.InvokeFunction("OnLoadingBegin", true, true);

                // Don't want to render the scene graph as its currently being loaded >.<.
                bool priorSceneGraphRender = true;
                if (_isServer == false)
                {
                    priorSceneGraphRender       = _window.RenderSceneGraph;
                    _window.RenderLoadingScreen = true;
                    _window.RenderSceneGraph    = false;
                }

                // Keep track of time :).
                HighPreformanceTimer loadTimer = new HighPreformanceTimer();

                // Get starting memory.
                long startingMemory = GC.GetTotalMemory(true);

                if (GraphicsManager.ThreadSafe == false)
                {
                    // Load the new map.
                    DebugLogger.WriteLog("Loading map from " + _mapLoadFile + " " + (_mapLoadPassword != "" ? " with password " + _mapLoadPassword : "") + ".");
                    LoadMapThread();
                }
                else
                {
                    // Load the new map.
                    DebugLogger.WriteLog("Loading map from " + _mapLoadFile + " " + (_mapLoadPassword != "" ? " with password " + _mapLoadPassword : "") + ".");
                    Thread thread = new Thread(LoadMapThread);
                    thread.Priority = ThreadPriority.Highest;
                    // Thread.CurrentThread.Priority = ThreadPriority.Lowest;
                    thread.IsBackground = true;
                    thread.Start();

                    // Ech, there has to be a better way than this. I hate thread safety >.>.
                    HighPreformanceTimer timer = new HighPreformanceTimer();
                    while (thread != null && thread.IsAlive == true)
                    {
                        // Track frame stats.
                        TrackFrameStatsBegin();

                        // Update the process.
                        //timer = new HighPreformanceTimer();
                        //_gameScriptProcess.Run(_deltaTime);
                        //_processProcessingDuration = (float)timer.DurationMillisecond;

                        // Update the graphical console.
                        if (_isServer == false)
                        {
                            GraphicalConsole.Update(1.0f);
                        }

                        // Tell the window to render
                        if (_isServer == false)
                        {
                            timer.Restart();
                            GraphicsCanvas.RenderAll();
                            _window.Render();
                            _renderingDuration = (float)timer.DurationMillisecond;
                        }

                        // Update network.
                        NetworkManager.Poll();

                        // Process application level events.
                        timer.Restart();
                        Application.DoEvents();
                        _applicationProcessingDuration = (float)timer.DurationMillisecond;

                        // Track frame stats.
                        TrackFrameStatsFinish();
                    }
                }

                // Invoke OnCreate events of scripted entities.
                foreach (SceneNode node in _map.SceneGraph.EnumerateNodes())
                {
                    if (node != null && node is ScriptedEntityNode && node.IsPersistent == false)
                    {
                        ((ScriptedEntityNode)node).ScriptProcess[0].InvokeFunction("OnCreate", true, false);
                    }
                }

                // Run the collision manager quickly so that we can sort out any unplesent problems.
                CollisionManager.ProcessCollisions();

                //Thread.CurrentThread.Priority = ThreadPriority.Normal;

                // We can render again! Oh holy days!
                if (_isServer == false)
                {
                    _window.RenderLoadingScreen = false;
                    _window.RenderSceneGraph    = priorSceneGraphRender;
                }

                // Remove any old resource from the cache that haven't been used for 5 maps :P.
                ResourceManager.CollectGarbage(3);

                // Free up some space.
                GC.Collect();

                // And we are done!
                DebugLogger.WriteLog("Map loaded successfully in " + loadTimer.DurationMillisecond + "ms, " + (((GC.GetTotalMemory(false) - startingMemory) / 1024.0f) / 1024.0f) + "mb allocated during loading.");

                // Yay, loaded!
                _mapLoadPending = false;

                // Reset the delta time!
                _forcedDeltaTimeThisFrame = 1.0f;
            }
        }