public byte[] Load( Stream stream, Game game, out int width, out int height, out int length )
        {
            byte[] map = null;
            width = 0;
            height = 0;
            length = 0;
            LocalPlayer p = game.LocalPlayer;
            p.Spawn = Vector3.Zero;
            GZipHeaderReader gsHeader = new GZipHeaderReader();
            while( !gsHeader.ReadHeader( stream ) ) { }

            using( DeflateStream gs = new DeflateStream( stream, CompressionMode.Decompress ) ) {
                reader = new BinaryReader( gs );
                ClassDescription obj = ReadData();
                for( int i = 0; i < obj.Fields.Length; i++ ) {
                    FieldDescription field = obj.Fields[i];
                    if( field.FieldName == "width" )
                        width = (int)field.Value;
                    else if( field.FieldName == "height" )
                        length = (int)field.Value;
                    else if( field.FieldName == "depth" )
                        height = (int)field.Value;
                    else if( field.FieldName == "blocks" )
                        map = (byte[])field.Value;
                    else if( field.FieldName == "xSpawn" )
                        p.Spawn.X = (int)field.Value;
                    else if( field.FieldName == "ySpawn" )
                        p.Spawn.Y = (int)field.Value;
                    else if( field.FieldName == "zSpawn" )
                        p.Spawn.Z = (int)field.Value;
                }
            }
            return map;
        }
        public byte[] Load( Stream stream, Game game, out int width, out int height, out int length )
        {
            GZipHeaderReader gsHeader = new GZipHeaderReader();
            while( !gsHeader.ReadHeader( stream ) ) { }

            using( DeflateStream gs = new DeflateStream( stream, CompressionMode.Decompress ) ) {
                BinaryReader reader = new BinaryReader( gs );
                ushort header = reader.ReadUInt16();

                width = header == Version ? reader.ReadUInt16() : header;
                length = reader.ReadUInt16();
                height = reader.ReadUInt16();

                LocalPlayer p = game.LocalPlayer;
                p.Spawn.X = reader.ReadUInt16();
                p.Spawn.Z = reader.ReadUInt16();
                p.Spawn.Y = reader.ReadUInt16();
                p.SpawnYaw = (float)Utils.PackedToDegrees( reader.ReadByte() );
                p.SpawnPitch = (float)Utils.PackedToDegrees( reader.ReadByte() );

                if( header == Version )
                    reader.ReadUInt16(); // pervisit and perbuild perms
                byte[] blocks = new byte[width * height * length];
                int read = gs.Read( blocks, 0, blocks.Length );
                ConvertPhysicsBlocks( blocks );

                if( gs.ReadByte() != 0xBD ) return blocks;
                ReadCustomBlocks( gs, width, height, length, blocks );
                return blocks;
            }
        }
        public byte[] Load( Stream stream, Game game, out int width, out int height, out int length )
        {
            GZipHeaderReader gsHeader = new GZipHeaderReader();
            while( !gsHeader.ReadHeader( stream ) ) { }

            using( DeflateStream gs = new DeflateStream( stream, CompressionMode.Decompress ) ) {
                reader = new BinaryReader( gs );
                if( reader.ReadByte() != (byte)NbtTagType.Compound )
                    throw new InvalidDataException( "Nbt file must start with Tag_Compound" );
                this.game = game;
                map = game.World;
                file = new NbtFile( reader );

                NbtTag root = file.ReadTag( (byte)NbtTagType.Compound, true );
                NbtCompound children = (NbtCompound)root.Value;
                if( children.ContainsKey( "Metadata" ) )
                    ParseMetadata( children );

                NbtCompound spawn = (NbtCompound)children["Spawn"].Value;
                LocalPlayer p = game.LocalPlayer;
                p.Spawn.X = (short)spawn["X"].Value;
                p.Spawn.Y = (short)spawn["Y"].Value;
                p.Spawn.Z = (short)spawn["Z"].Value;
                if( spawn.ContainsKey( "H" ) )
                    p.SpawnYaw = (float)Utils.PackedToDegrees( (byte)spawn["H"].Value );
                if( spawn.ContainsKey( "P" ) )
                    p.SpawnPitch = (float)Utils.PackedToDegrees( (byte)spawn["P"].Value );

                map.Uuid = new Guid( (byte[])children["UUID"].Value );
                width = (short)children["X"].Value;
                height = (short)children["Y"].Value;
                length = (short)children["Z"].Value;

                // Older versions incorrectly multiplied spawn coords by * 32, so we check for that.
                if( p.Spawn.X < 0 || p.Spawn.X >= width || p.Spawn.Y < 0 ||
                   p.Spawn.Y >= height || p.Spawn.Z < 0 || p.Spawn.Z >= length ) {
                    p.Spawn.X /= 32; p.Spawn.Y /= 32; p.Spawn.Z /= 32;
                }
                return (byte[])children["BlockArray"].Value;
            }
        }
        void HandleLevelInit()
        {
            if( gzipStream != null )
                return;
            game.World.Reset();
            prevScreen = game.activeScreen;
            if( prevScreen is LoadingMapScreen )
                prevScreen = null;
            prevCursorVisible = game.CursorVisible;

            game.SetNewScreen( new LoadingMapScreen( game, ServerName, ServerMotd ), false );
            if( ServerMotd.Contains( "cfg=" ) ) {
                ReadWomConfigurationAsync();
            }
            receivedFirstPosition = false;
            gzipHeader = new GZipHeaderReader();

            // Workaround because built in mono stream assumes that the end of stream
            // has been reached the first time a read call returns 0. (MS.NET doesn't)
            #if __MonoCS__
            gzipStream = new DeflateStream( gzippedMap, true );
            #else
            gzipStream = new DeflateStream( gzippedMap, CompressionMode.Decompress );
            if( OpenTK.Configuration.RunningOnMono ) {
                throw new InvalidOperationException( "You must compile ClassicalSharp with __MonoCS__ defined " +
                                                    "to run on Mono, due to a limitation in Mono." );
            }
            #endif

            mapSizeIndex = 0;
            mapIndex = 0;
            receiveStart = DateTime.UtcNow;
        }