Пример #1
0
 /// <summary>
 /// Tries reading a single packet from this stream. To read multiple available
 /// packets, repeatedly call this method until it returns <c>null</c>.
 /// </summary>
 /// <returns>
 /// A read packet, if one was available.
 /// </returns>
 /// <exception cref="System.IO.IOException">If the underlying stream fails.</exception>
 public IReadablePacket Read()
 {
     using (var packet = _stream.Read())
     {
         if (packet != null)
         {
             var compressed = packet.ReadBoolean();
             var data       = packet.ReadByteArray();
             if (compressed)
             {
                 data = SimpleCompression.Decompress(data);
             }
             return(new Packet(data, false));
         }
     }
     return(null);
 }
Пример #2
0
        /// <summary>
        ///     Create a new message, compressing it if it makes the message smaller, and encrypting it. Finally, we put the
        ///     header in front of it.
        /// </summary>
        /// <param name="packet">the packet to make a message of.</param>
        /// <returns>the message data.</returns>
        private byte[] MakeMessage(IWritablePacket packet)
        {
            // Get the actual data in raw format.
            var data   = packet.GetBuffer();
            var length = packet.Length;

            // If packets are large, try compressing them, see if it helps.
            // Only start after a certain size. General overhead for gzip
            // seems to be around 130byte, so make sure we're well beyond that.
            var flag = false;

            if (length > 200)
            {
                var compressed = SimpleCompression.Compress(data, length);
                if (compressed.Length < length)
                {
                    // OK, worth it, it's smaller than before.
                    flag   = true;
                    data   = compressed;
                    length = compressed.Length;
                }
            }

            // Encrypt the message.
            data = Crypto.Encrypt(data, 0, length);

            if ((length & CompressedMask) > 0)
            {
                throw new ArgumentException("Packet too big.", "packet");
            }

            // Build the final message: header, then length + compressed bit, then data.
            var result = new byte[_header.Length + sizeof(uint) + length];

            _header.CopyTo(result, 0);
            BitConverter.GetBytes((uint)length | (flag ? CompressedMask : 0u)).CopyTo(result, _header.Length);
            data.CopyTo(result, _header.Length + sizeof(uint));
            return(result);
        }
Пример #3
0
        /// <summary>
        /// Writes the specified packet to the underlying stream. It can then be read
        /// byte a <c>PacketStream</c> on the other end of the stream.
        /// </summary>
        /// <param name="packet">The packet to write.</param>
        /// <returns>The number of bytesa actually written. This can differ
        /// from the length of the specified packet due to transforms from
        /// wrapper streams (encryption, compression, ...)</returns>
        /// <exception cref="System.IO.IOException">If the underlying stream fails.</exception>
        public int Write(IWritablePacket packet)
        {
            using (var data = new Packet())
            {
                // If packets are large, try compressing them, see if it helps.
                // Only start after a certain size. General overhead for gzip
                // seems to be around 130byte, so make sure we're well beyond that.
                byte[] compressed;
                if (packet.Length > 200 && (compressed = SimpleCompression.Compress(packet.GetBuffer(), packet.Length)).Length < packet.Length)
                {
                    // OK, worth it, it's smaller than before.
                    data.Write(true);
                    data.Write(compressed);
                }
                else
                {
                    data.Write(false);
                    data.Write(packet.GetBuffer(), 0, packet.Length);
                }

                return(_stream.Write(data));
            }
        }
Пример #4
0
        /// <summary>Parse received data to check if it's a message we can handle, and parse it.</summary>
        /// <param name="message">the data to parse.</param>
        /// <returns>
        ///     the data parsed from the message, or <c>null</c> on failure.
        /// </returns>
        private IReadablePacket ParseMessage(byte[] message)
        {
            // Check the header.
            if (IsHeaderValid(message))
            {
                // Get message length plus compressed bit.
                var info   = BitConverter.ToUInt32(message, _header.Length);
                var length = (int)(info & ~CompressedMask);
                var flag   = (info & CompressedMask) > 0;

                // OK, get the decrypted packet.
                var data = Crypto.Decrypt(message, _header.Length + sizeof(uint), length);

                // Is this a compressed message?
                if (flag)
                {
                    data = SimpleCompression.Decompress(data);
                }

                // Return result as a packet.
                return(new Packet(data, false));
            }
            return(null);
        }
Пример #5
0
        /// <summary>Stores the profile to disk, under the specified profile name.</summary>
        public void Save()
        {
            // Get our plain data and hash it.
            var hasher = new Hasher();

            hasher.Write((byte)PlayerClass);
            if (_data != null)
            {
                hasher.Write(_data);
            }

            // Write it to a packet, compress it, encrypt it and save it.
            using (var packet = new Packet())
            {
                // Put our hash and plain data.
                packet.Write(Header);
                packet.Write(hasher.Value);
                packet.Write((byte)PlayerClass);
                packet.Write(_data);

                // Compress and encrypt, then save.
                var compressed = SimpleCompression.Compress(packet.GetBuffer(), packet.Length);
                var encrypted  = Crypto.Encrypt(compressed);

                var profilePath = GetFullProfilePath();
                try
                {
                    var path = Path.GetDirectoryName(profilePath);
                    if (path != null)
                    {
                        Directory.CreateDirectory(path);
                    }

                    // Make a backup if there's a save already.
                    if (File.Exists(profilePath))
                    {
                        var backupPath = profilePath + ".bak";
                        try
                        {
                            if (File.Exists(backupPath))
                            {
                                File.Delete(backupPath);
                            }
                            File.Move(profilePath, backupPath);
                        }
                        catch (Exception ex)
                        {
                            Logger.WarnException("Failed backing-up saved profile.", ex);
                        }
                    }

                    try
                    {
                        File.WriteAllBytes(profilePath, encrypted);
#if DEBUG
                        if (_data != null)
                        {
                            File.WriteAllBytes(profilePath + ".raw", (byte[])_data);
                        }
#endif
                    }
                    catch (Exception ex)
                    {
                        Logger.ErrorException("Failed saving profile.", ex);
                        // If we have a backup, try to restore it.
                        var backupPath = profilePath + ".bak";
                        if (File.Exists(backupPath))
                        {
                            try
                            {
                                if (File.Exists(profilePath))
                                {
                                    File.Delete(profilePath);
                                }
                                File.Copy(backupPath, profilePath);
                            }
                            catch (Exception ex2)
                            {
                                Logger.WarnException("Failed restoring backed-up profile.", ex2);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorException("Failed saving.", ex);
                }
            }
        }
Пример #6
0
        /// <summary>
        ///     Loads this profile from disk. If loading fails this will default to a new profile with the fall-back character
        ///     class.
        /// </summary>
        /// <exception cref="ArgumentException">Profile name is invalid.</exception>
        public void Load(string name)
        {
            if (InvalidCharPattern.IsMatch(name))
            {
                throw new ArgumentException(@"Invalid profile name, contains invalid character.", "name");
            }

            // Figure out the path, check if it's valid.
            Reset();
            Name = name;
            var profilePath = GetFullProfilePath();

            if (!File.Exists(profilePath))
            {
                throw new ArgumentException(@"Invalid profile name, no such file.", "name");
            }

            try
            {
                // Load the file contents, which are encrypted and compressed.
                var encrypted  = File.ReadAllBytes(profilePath);
                var compressed = Crypto.Decrypt(encrypted);
                var plain      = SimpleCompression.Decompress(compressed);

                // Now we have the plain data, handle it as a packet to read our
                // data from it.
                using (var packet = new Packet(plain, false))
                {
                    // Get file header.
                    if (!CheckHeader(packet.ReadByteArray()))
                    {
                        Logger.Error("Failed loading profile, invalid header, using default.");
                        return;
                    }

                    // Get the hash the data had when writing.
                    var hash = packet.ReadInt32();

                    // Get the player class.
                    var playerClass = (PlayerClassType)packet.ReadByte();

                    // And the actual data.
                    var data = packet.ReadPacketizable <Packet>();

                    // Check if the hash matches.
                    var hasher = new Hasher();
                    hasher.Write((byte)playerClass);
                    if (data != null)
                    {
                        hasher.Write(data);
                    }
                    if (hasher.Value == hash)
                    {
                        // All is well, keep the data, drop our old data, if any.
                        PlayerClass = playerClass;
                        _data       = data;
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorException("Failed loading profile, using default.", ex);
            }
        }
Пример #7
0
        /// <summary>Called when the specified key was pressed.</summary>
        /// <param name="key">The key that was pressed.</param>
        private void OnKeyDown(Keys key)
        {
            switch (key)
            {
            case Keys.Right:
                // Next test.
                LoadTest(_currentTest + 1);
                break;

            case Keys.Left:
                // Previous test
                LoadTest(_currentTest - 1);
                break;

            case Keys.Space:
                // Toggle pause.
                _running = !_running;
                break;

            case Keys.Tab:
            case Keys.Enter:
                // Manual step.
                _runOnce = true;
                break;

            case Keys.R:
                // Reset current test but keep camera and run settings.
                LoadTest(_currentTest, false);
                break;

            case Keys.K:
                // Create a snapshot via serialization.
                if (_manager != null)
                {
                    // Kill the mouse joint because deserializing it would
                    // cause a joint that we do not control anymore.
                    if (_mouseJoint >= 0)
                    {
                        _manager.RemoveJoint(_mouseJoint);
                        _mouseJoint = -1;
                    }

                    using (var w = new StreamWriter("before.txt"))
                    {
                        w.Dump(_manager);
                    }

                    _snapshot = new Packet();
                    _snapshot.Write(_manager);
                    var hasher = new Hasher();
                    hasher.Write(_manager);
                    _snapshotHash           = hasher.Value;
                    _snapshotCompressedSize =
                        SimpleCompression.Compress(_snapshot.GetBuffer(), _snapshot.Length).Length;
                }
                break;

            case Keys.L:
                // Load a previously created snapshot.
                if (_snapshot != null)
                {
                    // Reset test and stuff to avoid invalid references.
                    _mouseJoint = -1;
                    _snapshot.Reset();
                    _snapshot.ReadPacketizableInto(_manager);

                    var hasher = new Hasher();
                    hasher.Write(_manager);
                    Debug.Assert(_snapshotHash == hasher.Value);
                }
                break;

            case Keys.C:
                // Test copy implementation.
                if (_manager != null)
                {
                    var copy = new Manager();
                    copy.AddSystem(new ContentSystem(Content));
                    copy.AddSystem(new PhysicsSystem(1 / UpdatesPerSecond, new Vector2(0, -10f)));

                    copy.AddSystem(new ContentSystem(Content));
                    copy.AddSystem(new GraphicsDeviceSystem(_graphics));
                    copy.AddSystem(new DebugPhysicsRenderSystem {
                        Enabled = true, Scale = 0.1f, Offset = new WorldPoint(0, -12)
                    });

                    _manager.CopyInto(copy);
                    _manager.Clear();
                    copy.CopyInto(_manager);
                }
                break;

            case Keys.S:
                // Toggle whether sleeping is allowed.
                _physics.AllowSleep = !_physics.AllowSleep;
                break;

            case Keys.F1:
                // Toggle help display.
                _showHelp = !_showHelp;
                break;

            case Keys.F2:
                // Toggle profiler information.
                _showProfile = !_showProfile;
                break;

            case Keys.F3:
                // Toggle joints.
                _renderer.RenderJoints = !_renderer.RenderJoints;
                break;

            case Keys.F4:
                // Toggle contact point and normals.
                _renderer.RenderContactPoints  = !_renderer.RenderContactPoints;
                _renderer.RenderContactNormals = !_renderer.RenderContactNormals;
                break;

            case Keys.F5:
                // Toggle contact point normal impulse.
                _renderer.RenderContactPointNormalImpulse = !_renderer.RenderContactPointNormalImpulse;
                break;

            case Keys.F7:
                // Toggle center of mass.
                _renderer.RenderCenterOfMass = !_renderer.RenderCenterOfMass;
                break;

            case Keys.F8:
                // Toggle fixture bounding boxes.
                _renderer.RenderFixtureBounds = !_renderer.RenderFixtureBounds;
                break;
            }

            if (_manager != null)
            {
                Tests[_currentTest].OnKeyDown(key);
            }
        }