/// <summary> /// Updates and renders the game until the application becomes active /// (when it gets sent a message). /// </summary> /// <param name="sender">Object that called this method.</param> /// <param name="eventArgs">Arguments describing why this method was called.</param> private void MainLoop() { while (_closingDown == false) { // Reset statistics. // Statistics.StoreInt("Nodes Rendered", 0); // Hand back time to OS as we don't need it when the window is // minimized or not it focus. if (HandBackTimeToOS == true) { // Update essential stuff. Application.DoEvents(); Networking.NetworkManager.Poll(); // Sleep. Thread.Sleep(50); _deltaTimerOld = (float)_deltaTimer.DurationMillisecond; continue; } // Track frame stats. TrackFrameStatsBegin(); // Poll for new input. InputManager.Poll(); // Process new events. HighPreformanceTimer timer = new HighPreformanceTimer(); EventManager.ProcessEvents(); _eventProcessingDuration = (float)timer.DurationMillisecond; // Process processes. timer.Restart(); ProcessManager.RunProcesses(_deltaTime); _processProcessingDuration = (float)timer.DurationMillisecond; // Update the collision manager. timer.Restart(); CollisionManager.ProcessCollisions(); _collisionProcessingDuration = (float)timer.DurationMillisecond; // Update plugins. Plugin.CallPluginMethod("Update"); // Tell the abstraction layer that it can update. Update(); // Update the shader variables _bounceTimer1 += _bounceTimerDir == true ? (1.0f * _deltaTime) : -(1.0f * _deltaTime); if (_bounceTimer1 >= 100) _bounceTimerDir = false; else if (_bounceTimer1 <= 0) _bounceTimerDir = true; GraphicsManager.SetShaderVariable("deltaTime", _deltaTime); GraphicsManager.SetShaderVariable("frameCount", _frameCount); GraphicsManager.SetShaderVariable("timer1", _timer1 += (0.001f * _deltaTime)); GraphicsManager.SetShaderVariable("random1", MathMethods.Random(0.0f, 1.0f)); GraphicsManager.SetShaderVariable("random2", MathMethods.Random(0.0f, 1.0f)); GraphicsManager.SetShaderVariable("bounceTimer1", _bounceTimer1); // Render all canvases. timer.Restart(); if (_isServer == false) { if (_frameSkip == 0 || (++_frameSkipTracker % _frameSkip == 0)) GraphicsCanvas.RenderAll(); } _renderingDuration = (float)timer.DurationMillisecond; // Process application level events. timer.Restart(); Application.DoEvents(); _applicationProcessingDuration = (float)timer.DurationMillisecond; // Update the network. Networking.NetworkManager.Poll(); // Track frame stats. TrackFrameStatsFinish(); } }
/// <summary> /// Waits until a given packet is recieved and returns it. /// </summary> /// <param name="id">ID of packet to recieve. -1 for first available packet.</param> /// <param name="timeout">Maximum time to wait for packet.</param> /// <returns>Recieved packet.</returns> public NetworkPacket RecievePacket(int id, int timeout) { _asyncRecievePacketID = id; _asyncRecievePacket = null; HighPreformanceTimer timer = new HighPreformanceTimer(); while (true) { if (_asyncRecievePacket != null) return _asyncRecievePacket; Thread.Sleep(1); Application.DoEvents(); if (timer.DurationMillisecond > timeout) return null; } }
/// <summary> /// Renders the current state of the editor to the map canvas. And notifys /// any sub-windows to render themselfs. /// </summary> public void Render() { if (Form.ActiveForm == null || Engine.Engine.GlobalInstance.Map.SceneGraph == null) return; // Render the scene graph to the map canvas. HighPreformanceTimer renderTimer = new HighPreformanceTimer(); GraphicsManager.RenderTarget = (IRenderTarget)_mapCanvas; GraphicsManager.ClearColor = unchecked((int)0xFFFFFFFF); GraphicsManager.BeginScene(); // Make sure the viewport is correct. GraphicsManager.SetResolution(mapPanel.ClientSize.Width, mapPanel.ClientSize.Height, false); Editor.GlobalInstance.CameraNode.Viewport = new Rectangle(0, 0, mapPanel.ClientSize.Width, mapPanel.ClientSize.Height); // Render the scene graph. Engine.Engine.GlobalInstance.Map.SceneGraph.Render(); // Render the current tool. GraphicsManager.PushRenderState(); switch (_currentTool) { case Tools.Camera: break; case Tools.Ellipse: break; case Tools.Eraser: break; case Tools.PaintBucket: break; case Tools.Pencil: break; case Tools.Rectangle: break; case Tools.RoundedRectangle: break; case Tools.Line: break; case Tools.Selector: RenderSelector(); break; case Tools.TilePicker: break; } GraphicsManager.PopRenderState(); // Render the origin. if (_viewOrigin == true) { GraphicsManager.VertexColors.AllVertexs = unchecked((int)0xFF00FF00); GraphicsManager.RenderLine(0, -(Editor.GlobalInstance.CameraNode.Transformation.Y * Editor.GlobalInstance.CameraNode.Zoom), 0, _mapCanvas.RenderControl.ClientSize.Width, -(Editor.GlobalInstance.CameraNode.Transformation.Y * Editor.GlobalInstance.CameraNode.Zoom), 0); GraphicsManager.RenderLine(-(Editor.GlobalInstance.CameraNode.Transformation.X * Editor.GlobalInstance.CameraNode.Zoom), 0, 0, -(Editor.GlobalInstance.CameraNode.Transformation.X * Editor.GlobalInstance.CameraNode.Zoom), _mapCanvas.RenderControl.ClientSize.Height, 0); } GraphicsManager.FinishScene(); GraphicsManager.PresentScene(); // Update the FPS / rendering time status bars. this.fpsStatusLabel.Text = "Frames Per Second: " + Editor.GlobalInstance.CurrentFPS + "/" + Editor.GlobalInstance.FPSLimit; string renderTime = renderTimer.DurationMillisecond.ToString(); this.renderTimeStatusLabel.Text = "Rendering time: " + ((renderTime.IndexOf('.') > 0 ? renderTime.Substring(0, renderTime.IndexOf('.') + 2) : renderTime) + "ms").PadRight(5); int mapX = (int)Editor.GlobalInstance.CameraNode.Transformation.X + (int)((InputManager.MouseX / Editor.GlobalInstance.CameraNode.Zoom)); int mapY = (int)Editor.GlobalInstance.CameraNode.Transformation.Y + (int)((InputManager.MouseY / Editor.GlobalInstance.CameraNode.Zoom)); this.cursorPositionStatusLabel.Text = "X:" + (mapX.ToString().PadRight(4)) + " Y:" + (mapY.ToString().PadRight(4)) + " x:" + (InputManager.MouseX.ToString().PadRight(4)) + " y:" + (InputManager.MouseY.ToString().PadRight(4)); }
/// <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; } }
/// <summary> /// Entry point of the data download thread. /// </summary> private void DownloadThread() { try { // Open up a connection to the binary phoenix software updater. if (_socket != null) _socket.Close(); try { _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _socket.Connect(new IPAddress(Dns.GetHostEntry(_host).AddressList[0].GetAddressBytes()), 80); _socket.ReceiveTimeout = 5000; } catch (SocketException) { _error = "Unable to connect to host \"" + _host + "\"."; Debug.DebugLogger.WriteLog("An error occured while downloading '" + _url + "', \"" + _error + "\" "); if (ErrorOccured != null) ErrorOccured(this, _error); return; } _stream = new NetworkStream(_socket); // Build the post variables. int var = 0; string postRequest = ""; foreach (string key in _postVariables.Keys) { postRequest += (var != 0 ? "&" : "") + key + "=" + System.Web.HttpUtility.UrlEncode(_postVariables[key] as string); var++; } // Try and access the php updater file with the given account. string getRequest = (_method == DownloadMethod.POST ? "POST " : "GET ") + (_file + (postRequest != "" ? "&" + postRequest : "")).Replace(" ", "%20") + " HTTP/1.0\n" + "host: " + _host + "\n" + "user-agent: FusionDownloader\n" + "accept: * /*\n" + "connection: keep-alive\n" + "Keep-Alive: 300\n" + "cache-control: no-cache\n" + "content-type: application/x-www-form-urlencoded\n" + (_method == DownloadMethod.POST ? "content-length: " + postRequest.Length : "") + "\n"; _socket.Send(Encoding.ASCII.GetBytes(getRequest)); // Check this request went through OK. string result = ReadLineFromSocket(_socket); if (result.IndexOf("200 OK") < 0) { _error = "File \"" + _file + "\" does not exist on host \"" + _host + "\"."; Debug.DebugLogger.WriteLog("An error occured while downloading '" + _url + "', \"" + _error + "\" "); if (ErrorOccured != null) ErrorOccured(this, _error); return; } // Skip the header as we don't require it. string header = "#"; while (header != "") { header = ReadLineFromSocket(_socket); if (header.ToLower().StartsWith("content-length:") == true) _totalSize = int.Parse(header.Substring(15)); } // Create an array to hold the data downloaded. _fileData = new byte[_totalSize]; // Create a timer to use when tracking the speed of the download. HighPreformanceTimer timer = new HighPreformanceTimer(); if (_totalSize != 0) { while (_downloadedBytes < _totalSize) { // If this download has been paused then go to sleep for a little bit. while (_paused == true) Thread.Sleep(1); // Read in the next lot of data and quit if we don't recieve any. int bytesRead = 0; try { bytesRead = _socket.Receive(_fileData, _downloadedBytes, _totalSize - _downloadedBytes < 1024 ? _totalSize - _downloadedBytes : 1024, 0); if (bytesRead == 0) break; } catch (SocketException) { _error = "Download of \"" + _url + "\" was forceable stopped by the remote host."; Debug.DebugLogger.WriteLog("Download of \"" + _url + "\" was forceable stopped by the remote host."); if (ErrorOccured != null) ErrorOccured(this, _error); return; } // Update the amount of bytes downloaded and break out // of this loop if we haven't read in a full buffer. _downloadedBytes += bytesRead; // Keep track of the current download speed. if (timer.DurationMillisecond >= 1000) { timer.Restart(); _speed = (int)(((float)_downloadedBytes - (float)_speedTracker) / 1024.0f); _speedTracker = _downloadedBytes; // Push this speed onto the average stack. _averageCounter.Add(_speed); if (_averageCounter.Count > 20) _averageCounter.RemoveAt(0); // Work out the average speed. int total = 0; foreach (int avgSpeed in _averageCounter) total += avgSpeed; _averageSpeed = total / _averageCounter.Count; } // Invoke the update progress notification event. _progress = (int)((100.0f / (float)_totalSize) * (float)_downloadedBytes); if (ProgressUpdate != null) ProgressUpdate.Invoke(this, _progress); } // Check we managed to download the whole file. if (_fileData.Length != _totalSize) { _error = "Unable to download all data for \"" + _file + "\" expecting " + _totalSize + " bytes but got " + _fileData.Length + " bytes."; Debug.DebugLogger.WriteLog("An error occured while downloading '" + _url + "', \"" + _error + "\" "); if (ErrorOccured != null) ErrorOccured(this, _error); return; } } else { while (true) { // If this download has been paused then go to sleep for a little bit. while (_paused == true) Thread.Sleep(1); // Read in the next lot of data and quit if we don't recieve any. byte[] dataBuffer = new byte[1024]; int bytesRead = 0; try { bytesRead = _socket.Receive(dataBuffer, 1024, 0); } catch { _error = "Unable to download all data for \"" + _file + "\", require timed out."; Debug.DebugLogger.WriteLog("An error occured while downloading '" + _url + "', \"" + _error + "\" "); if (ErrorOccured != null) ErrorOccured(this, _error); return; } if (bytesRead == 0) break; // Convert the bytes into characters and append it to the data. if (_downloadedBytes + bytesRead - 1 > _fileData.Length) Array.Resize<byte>(ref _fileData, _downloadedBytes + bytesRead); for (int i = 0; i < bytesRead; i++) _fileData[_downloadedBytes + i] = dataBuffer[i]; _downloadedBytes += bytesRead; } } // Close the stream. _stream.Close(); _socket.Close(); _complete = true; Debug.DebugLogger.WriteLog("Downloaded file of " + _fileData.Length + " bytes from '" + _url + "'..."); } catch (Exception) { _error = "The server forceably closed the connection."; } }
/// <summary> /// Entry point of the data download thread. /// </summary> private void DownloadThread() { try { // Open up a connection to the binary phoenix software updater. if (_socket != null) { _socket.Close(); } try { _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _socket.Connect(new IPAddress(Dns.GetHostEntry(_host).AddressList[0].GetAddressBytes()), 80); _socket.ReceiveTimeout = 5000; } catch (SocketException) { _error = "Unable to connect to host \"" + _host + "\"."; Debug.DebugLogger.WriteLog("An error occured while downloading '" + _url + "', \"" + _error + "\" "); if (ErrorOccured != null) { ErrorOccured(this, _error); } return; } _stream = new NetworkStream(_socket); // Build the post variables. int var = 0; string postRequest = ""; foreach (string key in _postVariables.Keys) { postRequest += (var != 0 ? "&" : "") + key + "=" + System.Web.HttpUtility.UrlEncode(_postVariables[key] as string); var++; } // Try and access the php updater file with the given account. string getRequest = (_method == DownloadMethod.POST ? "POST " : "GET ") + (_file + (postRequest != "" ? "&" + postRequest : "")).Replace(" ", "%20") + " HTTP/1.0\n" + "host: " + _host + "\n" + "user-agent: FusionDownloader\n" + "accept: * /*\n" + "connection: keep-alive\n" + "Keep-Alive: 300\n" + "cache-control: no-cache\n" + "content-type: application/x-www-form-urlencoded\n" + (_method == DownloadMethod.POST ? "content-length: " + postRequest.Length : "") + "\n"; _socket.Send(Encoding.ASCII.GetBytes(getRequest)); // Check this request went through OK. string result = ReadLineFromSocket(_socket); if (result.IndexOf("200 OK") < 0) { _error = "File \"" + _file + "\" does not exist on host \"" + _host + "\"."; Debug.DebugLogger.WriteLog("An error occured while downloading '" + _url + "', \"" + _error + "\" "); if (ErrorOccured != null) { ErrorOccured(this, _error); } return; } // Skip the header as we don't require it. string header = "#"; while (header != "") { header = ReadLineFromSocket(_socket); if (header.ToLower().StartsWith("content-length:") == true) { _totalSize = int.Parse(header.Substring(15)); } } // Create an array to hold the data downloaded. _fileData = new byte[_totalSize]; // Create a timer to use when tracking the speed of the download. HighPreformanceTimer timer = new HighPreformanceTimer(); if (_totalSize != 0) { while (_downloadedBytes < _totalSize) { // If this download has been paused then go to sleep for a little bit. while (_paused == true) { Thread.Sleep(1); } // Read in the next lot of data and quit if we don't recieve any. int bytesRead = 0; try { bytesRead = _socket.Receive(_fileData, _downloadedBytes, _totalSize - _downloadedBytes < 1024 ? _totalSize - _downloadedBytes : 1024, 0); if (bytesRead == 0) { break; } } catch (SocketException) { _error = "Download of \"" + _url + "\" was forceable stopped by the remote host."; Debug.DebugLogger.WriteLog("Download of \"" + _url + "\" was forceable stopped by the remote host."); if (ErrorOccured != null) { ErrorOccured(this, _error); } return; } // Update the amount of bytes downloaded and break out // of this loop if we haven't read in a full buffer. _downloadedBytes += bytesRead; // Keep track of the current download speed. if (timer.DurationMillisecond >= 1000) { timer.Restart(); _speed = (int)(((float)_downloadedBytes - (float)_speedTracker) / 1024.0f); _speedTracker = _downloadedBytes; // Push this speed onto the average stack. _averageCounter.Add(_speed); if (_averageCounter.Count > 20) { _averageCounter.RemoveAt(0); } // Work out the average speed. int total = 0; foreach (int avgSpeed in _averageCounter) { total += avgSpeed; } _averageSpeed = total / _averageCounter.Count; } // Invoke the update progress notification event. _progress = (int)((100.0f / (float)_totalSize) * (float)_downloadedBytes); if (ProgressUpdate != null) { ProgressUpdate.Invoke(this, _progress); } } // Check we managed to download the whole file. if (_fileData.Length != _totalSize) { _error = "Unable to download all data for \"" + _file + "\" expecting " + _totalSize + " bytes but got " + _fileData.Length + " bytes."; Debug.DebugLogger.WriteLog("An error occured while downloading '" + _url + "', \"" + _error + "\" "); if (ErrorOccured != null) { ErrorOccured(this, _error); } return; } } else { while (true) { // If this download has been paused then go to sleep for a little bit. while (_paused == true) { Thread.Sleep(1); } // Read in the next lot of data and quit if we don't recieve any. byte[] dataBuffer = new byte[1024]; int bytesRead = 0; try { bytesRead = _socket.Receive(dataBuffer, 1024, 0); } catch { _error = "Unable to download all data for \"" + _file + "\", require timed out."; Debug.DebugLogger.WriteLog("An error occured while downloading '" + _url + "', \"" + _error + "\" "); if (ErrorOccured != null) { ErrorOccured(this, _error); } return; } if (bytesRead == 0) { break; } // Convert the bytes into characters and append it to the data. if (_downloadedBytes + bytesRead - 1 > _fileData.Length) { Array.Resize <byte>(ref _fileData, _downloadedBytes + bytesRead); } for (int i = 0; i < bytesRead; i++) { _fileData[_downloadedBytes + i] = dataBuffer[i]; } _downloadedBytes += bytesRead; } } // Close the stream. _stream.Close(); _socket.Close(); _complete = true; Debug.DebugLogger.WriteLog("Downloaded file of " + _fileData.Length + " bytes from '" + _url + "'..."); } catch (Exception) { _error = "The server forceably closed the connection."; } }