Exemple #1
0
		public static ChunkColumn DecocedChunkColumn(byte[] buffer)
		{
			return null;
			MemoryStream stream = new MemoryStream(buffer);
			{
				NbtBinaryReader defStream = new NbtBinaryReader(stream, true);
				ChunkColumn chunk = new ChunkColumn();

				chunk.x = IPAddress.NetworkToHostOrder(defStream.ReadInt32());
				chunk.z = IPAddress.NetworkToHostOrder(defStream.ReadInt32());

				int chunkSize = 16*16*128;
				defStream.Read(chunk.blocks, 0, chunkSize);
				defStream.Read(chunk.metadata.Data, 0, chunkSize/2);
				defStream.Read(chunk.skylight.Data, 0, chunkSize/2);
				defStream.Read(chunk.blocklight.Data, 0, chunkSize/2);

				defStream.Read(chunk.height, 0, 256);

				byte[] ints = new byte[256*4];
				defStream.Read(ints, 0, ints.Length);
				int j = 0;
				for (int i = 0; i < ints.Length; i = i + 4)
				{
					chunk.biomeColor[j++] = BitConverter.ToInt32(new[] {ints[i], ints[i + 1], ints[i + 2], ints[i + 3]}, 0);
				}

				return chunk;
			}
		}
Exemple #2
0
        static string GetRootNameInternal([NotNull] Stream stream, bool bigEndian)
        {
            Debug.Assert(stream != null);
            int firstByte = stream.ReadByte();

            if (firstByte < 0)
            {
                throw new EndOfStreamException();
            }
            else if (firstByte != (int)NbtTagType.Compound)
            {
                throw new NbtFormatException("Given NBT stream does not start with a TAG_Compound");
            }
            var reader = new NbtBinaryReader(stream, bigEndian);

            return(reader.ReadString());
        }
Exemple #3
0
        private void OnBatch(Package message)
        {
            McpeBatch batch = (McpeBatch)message;

            var messages = new List <Package>();

            // Get bytes
            byte[] payload = batch.payload;
            // Decompress bytes

            MemoryStream stream = new MemoryStream(payload);

            if (stream.ReadByte() != 0x78)
            {
                throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
            }
            stream.ReadByte();
            using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
            {
                // Get actual package out of bytes
                MemoryStream destination = new MemoryStream();
                defStream2.CopyTo(destination);
                destination.Position = 0;
                NbtBinaryReader reader = new NbtBinaryReader(destination, true);
                do
                {
                    int    len            = reader.ReadInt32();
                    byte[] internalBuffer = reader.ReadBytes(len);
                    var    package        = PackageFactory.CreatePackage(internalBuffer[0], internalBuffer) ?? new UnknownPackage(internalBuffer[0], internalBuffer);
                    messages.Add(package);

                    if (!(package is McpeFullChunkData))
                    {
                        Log.Debug($"Batch: {package.GetType().Name} 0x{package.Id:x2} \n{Package.HexDump(internalBuffer)}");
                    }
                } while (destination.Position < destination.Length);
            }
            foreach (var msg in messages)
            {
                msg.DatagramSequenceNumber = batch.DatagramSequenceNumber;
                msg.OrderingChannel        = batch.OrderingChannel;
                msg.OrderingIndex          = batch.OrderingIndex;
                HandlePackage(msg);
                msg.PutPool();
            }
        }
Exemple #4
0
        internal override bool ReadTag(NbtBinaryReader readStream)
        {
            int length = readStream.ReadInt32();
            if (length < 0)
            {
                throw new NbtFormatException("Negative length given in TAG_Byte_Array");
            }

            if (readStream.Selector != null && !readStream.Selector(this))
            {
                readStream.Skip(length);
                return false;
            }
            Value = readStream.ReadBytes(length);
            if (Value.Length < length)
            {
                throw new EndOfStreamException();
            }
            return true;
        }
Exemple #5
0
        internal override bool ReadTag(NbtBinaryReader readStream)
        {
            int length = readStream.ReadInt32();

            if (length < 0)
            {
                throw new NbtFormatException("Negative length given in TAG_Int_Array");
            }

            if (readStream.Selector != null && !readStream.Selector(this))
            {
                readStream.Skip(length * sizeof(int));
                return(false);
            }

            Value = new int[length];
            for (int i = 0; i < length; i++)
            {
                Value[i] = readStream.ReadInt32();
            }
            return(true);
        }
Exemple #6
0
        private List <Package> HandleBatch(McpeWrapper batch)
        {
            var messages = new List <Package>();

            // Get bytes
            byte[] payload = batch.payload;
            // Decompress bytes

            Console.WriteLine("Package:\n" + Package.HexDump(payload));

            MemoryStream stream = new MemoryStream(payload);

            if (stream.ReadByte() != 0x78)
            {
                throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
            }
            stream.ReadByte();
            using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
            {
                // Get actual package out of bytes
                MemoryStream destination = new MemoryStream();
                defStream2.CopyTo(destination);
                destination.Position = 0;
                NbtBinaryReader reader         = new NbtBinaryReader(destination, true);
                int             len            = reader.ReadInt32();
                byte[]          internalBuffer = reader.ReadBytes(len);

                Console.WriteLine($"Package [len={len}:\n" + Package.HexDump(internalBuffer));

                messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer, "mcpe") ?? new UnknownPackage(internalBuffer[0], internalBuffer));
                if (destination.Length > destination.Position)
                {
                    throw new Exception("Have more data");
                }
            }

            return(messages);
        }
Exemple #7
0
        void LoadFromStreamInternal([NotNull] Stream stream, [CanBeNull] TagSelector tagSelector)
        {
            // Make sure the first byte in this file is the tag for a TAG_Compound
            int firstByte = stream.ReadByte();

            if (firstByte < 0)
            {
                throw new EndOfStreamException();
            }
            if (firstByte != (int)NbtTagType.Compound)
            {
                throw new NbtFormatException("Given NBT stream does not start with a TAG_Compound");
            }
            var reader = new NbtBinaryReader(stream, BigEndian)
            {
                Selector = tagSelector
            };

            var rootCompound = new NbtCompound(reader.ReadString());

            rootCompound.ReadTag(reader);
            RootTag = rootCompound;
        }
Exemple #8
0
        internal static bool ReadTag(this NbtTag tag, NbtBinaryReader readStream)
        {
            while (true)
            {
                NbtTag nbtTag;
                do
                {
                    NbtTagType nbtTagType = readStream.ReadTagType();
                    switch (nbtTagType)
                    {
                    case NbtTagType.End:
                        return(true);

                    case NbtTagType.Byte:
                        nbtTag = (NbtTag) new NbtByte();
                        break;

                    case NbtTagType.Short:
                        nbtTag = (NbtTag) new NbtShort();
                        break;

                    case NbtTagType.Int:
                        nbtTag = (NbtTag) new NbtInt();
                        break;

                    case NbtTagType.Long:
                        nbtTag = (NbtTag) new NbtLong();
                        break;

                    case NbtTagType.Float:
                        nbtTag = (NbtTag) new NbtFloat();
                        break;

                    case NbtTagType.Double:
                        nbtTag = (NbtTag) new NbtDouble();
                        break;

                    case NbtTagType.ByteArray:
                        nbtTag = (NbtTag) new NbtByteArray();
                        break;

                    case NbtTagType.String:
                        nbtTag = (NbtTag) new NbtString();
                        break;

                    case NbtTagType.List:
                        nbtTag = (NbtTag) new NbtList();
                        break;

                    case NbtTagType.Compound:
                        nbtTag = (NbtTag) new NbtCompound();
                        break;

                    case NbtTagType.IntArray:
                        nbtTag = (NbtTag) new NbtIntArray();
                        break;

                    case NbtTagType.LongArray:
                        nbtTag = (NbtTag) new NbtLongArray();
                        break;

                    case NbtTagType.Unknown:
                        return(true);

                        break;

                    default:
                        throw new FormatException("Unsupported tag type found in NBT_Compound: " + (object)nbtTagType);
                    }
                    //nbtTag.Parent = (NbtTag) this;
                    nbtTag.Name = readStream.ReadString();
                }while (!nbtTag.ReadTag(readStream));

                switch (tag.TagType)
                {
                case NbtTagType.Compound:
                    NbtCompound compound = (NbtCompound)tag;
                    compound.Add(nbtTag);
                    break;

                case NbtTagType.List:
                    NbtList list = (NbtList)tag;
                    list.Add(nbtTag);
                    break;
                }
            }
        }
Exemple #9
0
 internal abstract bool ReadTag([NotNull] NbtBinaryReader readStream);
Exemple #10
0
 internal override void SkipTag(NbtBinaryReader readStream)
 {
     readStream.ReadInt16();
 }
Exemple #11
0
 internal override void SkipTag(NbtBinaryReader readStream) => readStream.ReadDouble();
Exemple #12
0
        internal void HandlePackage(Package message, PlayerNetworkSession playerSession)
        {
            if (message == null)
            {
                return;
            }

            TraceReceive(message);

            if (typeof(UnknownPackage) == message.GetType())
            {
                UnknownPackage packet = (UnknownPackage)message;
                Log.Warn($"Received unknown package 0x{message.Id:X2}\n{Package.HexDump(packet.Message)}");
                return;
            }

            if (typeof(McpeBatch) == message.GetType())
            {
                McpeBatch batch = (McpeBatch)message;

                var messages = new List <Package>();

                // Get bytes
                byte[] payload = batch.payload;
                // Decompress bytes

                MemoryStream stream = new MemoryStream(payload);
                if (stream.ReadByte() != 0x78)
                {
                    throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
                }
                stream.ReadByte();
                using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
                {
                    // Get actual package out of bytes
                    MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream();
                    defStream2.CopyTo(destination);
                    destination.Position = 0;
                    NbtBinaryReader reader         = new NbtBinaryReader(destination, true);
                    int             len            = reader.ReadInt32();
                    byte[]          internalBuffer = reader.ReadBytes(len);

                    //byte[] internalBuffer = destination.ToArray();
                    messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer) ?? new UnknownPackage(internalBuffer[0], internalBuffer));
                    if (destination.Length > destination.Position)
                    {
                        throw new Exception("Have more data");
                    }
                }
                foreach (var msg in messages)
                {
                    msg.DatagramSequenceNumber = batch.DatagramSequenceNumber;
                    msg.OrderingChannel        = batch.OrderingChannel;
                    msg.OrderingIndex          = batch.OrderingIndex;
                    HandlePackage(msg, playerSession);
                    msg.PutPool();
                }

                return;
            }

            Player player = playerSession.Player;

            if (player != null)
            {
                player.HandlePackage(message);
            }
        }
Exemple #13
0
        public static ChunkColumn DecodeChunkColumn(int subChunkCount, byte[] buffer, BlockPalette bedrockPalette = null, HashSet <BlockStateContainer> internalBlockPallet = null)
        {
            lock (_chunkRead)
            {
                var stream = new MemoryStream(buffer);
                {
                    var defStream = new NbtBinaryReader(stream, true);

                    if (subChunkCount < 1)
                    {
                        Log.Warn("Nothing to read");
                        return(null);
                    }

                    Log.Debug($"Reading {subChunkCount} sections");

                    var chunkColumn = new ChunkColumn(false);

                    for (int chunkIndex = 0; chunkIndex < subChunkCount; chunkIndex++)
                    {
                        int version     = defStream.ReadByte();
                        int storageSize = defStream.ReadByte();

                        var subChunk = chunkColumn[chunkIndex];

                        for (int storageIndex = 0; storageIndex < storageSize; storageIndex++)
                        {
                            int bitsPerBlock  = defStream.ReadByte() >> 1;
                            int blocksPerWord = (int)Math.Floor(32f / bitsPerBlock);
                            int wordsPerChunk = (int)Math.Ceiling(4096f / blocksPerWord);
                            Log.Debug($"New section {chunkIndex}, " +
                                      $"version={version}, " +
                                      $"storageSize={storageSize}, " +
                                      $"storageIndex={storageIndex}, " +
                                      $"bitsPerBlock={bitsPerBlock}, " +
                                      $"noBlocksPerWord={blocksPerWord}, " +
                                      $"wordCount={wordsPerChunk}, " +
                                      $"");


                            long jumpPos = stream.Position;
                            stream.Seek(wordsPerChunk * 4, SeekOrigin.Current);

                            int paletteCount = VarInt.ReadSInt32(stream);
                            var palette      = new int[paletteCount];
                            for (int j = 0; j < paletteCount; j++)
                            {
                                int runtimeId = VarInt.ReadSInt32(stream);
                                if (bedrockPalette == null || internalBlockPallet == null)
                                {
                                    continue;
                                }

                                palette[j] = GetServerRuntimeId(bedrockPalette, internalBlockPallet, runtimeId);
                            }

                            long afterPos = stream.Position;
                            stream.Position = jumpPos;
                            int position = 0;
                            for (int w = 0; w < wordsPerChunk; w++)
                            {
                                uint word = defStream.ReadUInt32();
                                for (int block = 0; block < blocksPerWord; block++)
                                {
                                    if (position >= 4096)
                                    {
                                        continue;
                                    }

                                    uint state = (uint)((word >> ((position % blocksPerWord) * bitsPerBlock)) & ((1 << bitsPerBlock) - 1));

                                    int x = (position >> 8) & 0xF;
                                    int y = position & 0xF;
                                    int z = (position >> 4) & 0xF;

                                    int runtimeId = palette[state];

                                    if (storageIndex == 0)
                                    {
                                        subChunk.SetBlockByRuntimeId(x, y, z, (int)runtimeId);
                                    }
                                    else
                                    {
                                        subChunk.SetLoggedBlockByRuntimeId(x, y, z, (int)runtimeId);
                                    }

                                    position++;
                                }
                            }
                            stream.Position = afterPos;
                        }
                    }

                    if (defStream.Read(chunkColumn.biomeId, 0, 256) != 256)
                    {
                        Log.Error($"Out of data biomeId");
                    }
                    //Log.Debug($"biomeId:\n{Package.HexDump(chunk.biomeId)}");

                    //if (stream.Position >= stream.Length - 1) return chunkColumn;

                    int borderBlock = VarInt.ReadSInt32(stream);
                    if (borderBlock != 0)
                    {
                        byte[] buf = new byte[borderBlock];
                        int    len = defStream.Read(buf, 0, borderBlock);
                        Log.Warn($"??? Got borderblock {borderBlock}. Read {len} bytes");
                        Log.Debug($"{Packet.HexDump(buf)}");
                        for (int i = 0; i < borderBlock; i++)
                        {
                            int x = (buf[i] & 0xf0) >> 4;
                            int z = buf[i] & 0x0f;
                            Log.Debug($"x={x}, z={z}");
                        }
                    }

                    if (stream.Position < stream.Length - 1)
                    {
                        while (stream.Position < stream.Length)
                        {
                            NbtFile file = new NbtFile()
                            {
                                BigEndian = false,
                                UseVarInt = true
                            };

                            file.LoadFromStream(stream, NbtCompression.None);
                            var blockEntityTag = file.RootTag;
                            if (blockEntityTag.Name != "alex")
                            {
                                int x = blockEntityTag["x"].IntValue;
                                int y = blockEntityTag["y"].IntValue;
                                int z = blockEntityTag["z"].IntValue;

                                chunkColumn.SetBlockEntity(new BlockCoordinates(x, y, z), (NbtCompound)file.RootTag);

                                Log.Debug($"Blockentity:\n{file.RootTag}");
                            }
                        }
                    }
                    if (stream.Position < stream.Length - 1)
                    {
                        Log.Warn($"Still have data to read\n{Packet.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");
                    }

                    return(chunkColumn);
                }
            }
        }
Exemple #14
0
        internal override bool ReadTag(NbtBinaryReader readStream)
        {
            int length = readStream.ReadInt32();
            if (length < 0)
            {
                throw new NbtFormatException("Negative length given in TAG_Int_Array");
            }

            if (readStream.Selector != null && !readStream.Selector(this))
            {
                readStream.Skip(length * sizeof(int));
                return false;
            }

            Value = new int[length];
            for (int i = 0; i < length; i++)
            {
                Value[i] = readStream.ReadInt32();
            }
            return true;
        }
Exemple #15
0
        internal override bool ReadTag(NbtBinaryReader readStream)
        {
            int length = readStream.ReadInt32();
            if (length < 0)
            {
                throw new NbtFormatException("Negative length given in TAG_Byte_Array");
            }

            if (readStream.Selector != null && !readStream.Selector(this))
            {
                readStream.Skip(length);
                return false;
            }
            Value = readStream.ReadBytes(length);
            if (Value.Length < length)
            {
                throw new EndOfStreamException();
            }
            return true;
        }
Exemple #16
0
        private void HandleChunk(byte[] chunkData, int cx, int cz, Action <ChunkColumn> callback)
        {
            MeasureProfiler.StartCollectingData();
            var profiler = MiniProfiler.StartNew("BEToJavaColumn");

            try
            {
                using (MemoryStream stream = new MemoryStream(chunkData))
                {
                    NbtBinaryReader defStream = new NbtBinaryReader(stream, true);

                    int count = defStream.ReadByte();
                    if (count < 1)
                    {
                        Log.Warn("Nothing to read");
                        return;
                    }

                    ChunkColumn chunkColumn = new ChunkColumn();
                    chunkColumn.IsDirty = true;
                    chunkColumn.X       = cx;
                    chunkColumn.Z       = cz;

                    for (int s = 0; s < count; s++)
                    {
                        var section = chunkColumn.Sections[s] as ChunkSection;
                        if (section == null)
                        {
                            section = new ChunkSection(s, true);
                        }

                        int version = defStream.ReadByte();

                        if (version == 1 || version == 8)
                        {
                            int storageSize = defStream.ReadByte();

                            for (int storage = 0; storage < storageSize; storage++)
                            {
                                int  paletteAndFlag = defStream.ReadByte();
                                bool isRuntime      = (paletteAndFlag & 1) != 0;
                                int  bitsPerBlock   = paletteAndFlag >> 1;
                                int  blocksPerWord  = (int)Math.Floor(32f / bitsPerBlock);
                                int  wordCount      = (int)Math.Ceiling(4096.0f / blocksPerWord);

                                uint[] words = new uint[wordCount];
                                for (int w = 0; w < wordCount; w++)
                                {
                                    int word = defStream.ReadInt32();
                                    words[w] = SwapBytes((uint)word);
                                }

                                uint[] pallete = new uint[0];

                                if (isRuntime)
                                {
                                    int palleteSize = VarInt.ReadSInt32(stream);
                                    pallete = new uint[palleteSize];

                                    for (int pi = 0; pi < pallete.Length; pi++)
                                    {
                                        var ui = (uint)VarInt.ReadSInt32(stream);
                                        pallete[pi] = ui;
                                    }

                                    if (palleteSize == 0)
                                    {
                                        Log.Warn($"Pallete size is 0");
                                        continue;
                                    }
                                }

                                int position = 0;
                                for (int w = 0; w < wordCount; w++)
                                {
                                    uint word = words[w];
                                    for (int block = 0; block < blocksPerWord; block++)
                                    {
                                        if (position >= 4096)
                                        {
                                            break;                                                   // padding bytes
                                        }
                                        uint state =
                                            (uint)((word >> ((position % blocksPerWord) * bitsPerBlock)) &
                                                   ((1 << bitsPerBlock) - 1));
                                        int x = (position >> 8) & 0xF;
                                        int y = position & 0xF;
                                        int z = (position >> 4) & 0xF;

                                        if (storage == 0)
                                        {
                                            if (state >= pallete.Length)
                                            {
                                                continue;
                                            }

                                            IBlockState translated = _convertedStates.GetOrAdd(pallete[state],
                                                                                               u =>
                                            {
                                                if (_blockStateMap.TryGetValue(pallete[state], out var bs))
                                                {
                                                    var result =
                                                        BlockFactory.RuntimeIdTable.FirstOrDefault(xx =>
                                                                                                   xx.Name == bs.Name);

                                                    if (result != null && result.Id >= 0)
                                                    {
                                                        var reverseMap = MiNET.Worlds.AnvilWorldProvider.Convert.FirstOrDefault(map =>
                                                                                                                                map.Value.Item1 == result.Id);

                                                        var id = result.Id;
                                                        if (reverseMap.Value != null)
                                                        {
                                                            id = reverseMap.Key;
                                                        }

                                                        var res = BlockFactory.GetBlockStateID(
                                                            (int)id,
                                                            (byte)bs.Data);

                                                        if (AnvilWorldProvider.BlockStateMapper.TryGetValue(
                                                                res,
                                                                out var res2))
                                                        {
                                                            var t = BlockFactory.GetBlockState(res2);
                                                            t     = TranslateBlockState(t, id,
                                                                                        bs.Data);

                                                            return(t);
                                                        }
                                                        else
                                                        {
                                                            Log.Info(
                                                                $"Did not find anvil statemap: {result.Name}");
                                                            return(TranslateBlockState(
                                                                       BlockFactory.GetBlockState(result.Name),
                                                                       id, bs.Data));
                                                        }
                                                    }

                                                    return(TranslateBlockState(
                                                               BlockFactory.GetBlockState(bs.Name),
                                                               -1, bs.Data));
                                                }

                                                return(null);
                                            });

                                            if (translated != null)
                                            {
                                                section.Set(x, y, z, translated);
                                            }
                                        }
                                        else
                                        {
                                            //TODO.
                                        }

                                        position++;
                                    }

                                    if (position >= 4096)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            #region OldFormat

                            byte[] blockIds = new byte[4096];
                            defStream.Read(blockIds, 0, blockIds.Length);

                            NibbleArray data = new NibbleArray(4096);
                            defStream.Read(data.Data, 0, data.Data.Length);

                            for (int x = 0; x < 16; x++)
                            {
                                for (int z = 0; z < 16; z++)
                                {
                                    for (int y = 0; y < 16; y++)
                                    {
                                        int idx  = (x << 8) + (z << 4) + y;
                                        var id   = blockIds[idx];
                                        var meta = data[idx];

                                        IBlockState result = null;

                                        if (id > 0 && result == null)
                                        {
                                            var res = BlockFactory.GetBlockStateID(id, meta);

                                            if (AnvilWorldProvider.BlockStateMapper.TryGetValue(res,
                                                                                                out var res2))
                                            {
                                                var t = BlockFactory.GetBlockState(res2);
                                                t = TranslateBlockState(t, id,
                                                                        meta);

                                                result = t;
                                            }
                                            else
                                            {
                                                Log.Info($"Did not find anvil statemap: {result.Name}");
                                                result = TranslateBlockState(BlockFactory.GetBlockState(res),
                                                                             id, meta);
                                            }
                                        }

                                        if (result == null)
                                        {
                                            var results = BlockFactory.RuntimeIdTable.Where(xx =>
                                                                                            xx.Id == id && xx.Data == meta).ToArray();

                                            if (results.Length > 0)
                                            {
                                                result = TranslateBlockState(
                                                    BlockFactory.GetBlockState((uint)results[0].RuntimeId), id,
                                                    meta);
                                            }
                                        }

                                        if (result != null)
                                        {
                                            section.Set(x, y, z, result);
                                        }
                                    }
                                }
                            }

                            #endregion
                        }

                        if (UseAlexChunks)
                        {
                            //  Log.Info($"Alex chunk!");

                            var rawSky = new Utils.NibbleArray(4096);
                            defStream.Read(rawSky.Data, 0, rawSky.Data.Length);

                            var rawBlock = new Utils.NibbleArray(4096);
                            defStream.Read(rawBlock.Data, 0, rawBlock.Data.Length);

                            for (int x = 0; x < 16; x++)
                            {
                                for (int y = 0; y < 16; y++)
                                {
                                    for (int z = 0; z < 16; z++)
                                    {
                                        var peIndex = (x * 256) + (z * 16) + y;
                                        var sky     = rawSky[peIndex];
                                        var block   = rawBlock[peIndex];

                                        var idx = y << 8 | z << 4 | x;

                                        section.SkyLight[idx]   = sky;
                                        section.BlockLight[idx] = block;
                                    }
                                }
                            }
                        }

                        section.RemoveInvalidBlocks();
                        section.IsDirty = true;

                        //Make sure the section is saved.
                        chunkColumn.Sections[s] = section;
                    }


                    byte[] ba = new byte[512];
                    if (defStream.Read(ba, 0, 256 * 2) != 256 * 2)
                    {
                        Log.Error($"Out of data height");
                    }

                    Buffer.BlockCopy(ba, 0, chunkColumn.Height, 0, 512);

                    int[] biomeIds = new int[256];
                    for (int i = 0; i < biomeIds.Length; i++)
                    {
                        biomeIds[i] = defStream.ReadByte();
                    }

                    chunkColumn.BiomeId = biomeIds;

                    if (stream.Position >= stream.Length - 1)
                    {
                        callback?.Invoke(chunkColumn);
                        return;
                    }

                    int borderBlock = VarInt.ReadSInt32(stream);
                    if (borderBlock > 0)
                    {
                        byte[] buf = new byte[borderBlock];
                        int    len = defStream.Read(buf, 0, borderBlock);
                    }


                    if (stream.Position < stream.Length - 1)
                    {
                        while (stream.Position < stream.Length)
                        {
                            NbtFile file = new NbtFile()
                            {
                                BigEndian = false,
                                UseVarInt = true
                            };

                            file.LoadFromStream(stream, NbtCompression.None);
                        }
                    }

                    if (stream.Position < stream.Length - 1)
                    {
                        Log.Warn(
                            $"Still have data to read\n{Packet.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");
                    }

                    //Done processing this chunk, send to world
                    callback?.Invoke(chunkColumn);
                }
            }
            catch (Exception ex)
            {
                Log.Error($"Exception in chunk loading: {ex.ToString()}");
            }
            finally
            {
                profiler?.Stop();
                MeasureProfiler.SaveData();
            }
        }
		public void LabTest()
		{
			// x = 8, z = 9
			string test = "78daedcdc109c0200004c1233e125bb32f1b4a836a170acec0bef74b52576f294f36f2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f73fe10f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002718974bff9ba43b9b1d578f30";
			string test2 = "789ced5dc9721cc711ed8e09c5486341185877872f085c110179df480220099120294ba47ce4cd115ee99dd64aefa6f7332fd09d3cf80374d00f38829f40ff8088b32f7067cfd44cf774d792f5b23bd14065c470d033fdea655657d6cbaa6e80af6459f6bf939393f1789c57acf8340fb6a3a3a39733d0e6fc930991133d833f17e1cfc7444f0ecc3ee93ffe71959f15be007f3eeffff202f0f865fabf320099f422fc4533c6017ef862e33f8a5f26fe053f9b5ee8fa03e10b8f3fae29f34b8f3f1dfe687ac9f94f317e881f76405dfff3790130e3ee9f7fbcd0bfd907e1f452f3ef78c63fc9caf8fbe65fc43fe130cfe9cfc4fc5b51400dfee8f2435d7fb5f9e5eb2f6ef8eaf3ff19e08fa63f23f143f59f80fee7d50a28eb5f7fabf31f73052837fee6facfe0968bdf6c40b0f985d6bf950d0085f8e76d45d0abafbf64f54fe9fa2ff29ff835f47fd15a04bd74fdc1e3971a7fb1035078fe55e257d75f845f447f117ed401b3fe9e5ba6a0ff739b1075fffbdfcb05302bf64ef879f4a2fb5f31fa2fa93f547ff1e985f557833f371ea88dbf65fc4af5472cbfdcfdb799a95cff61eb9f363faebfd8febf84feeaf2afeefff3f8a5f59f1bff19e05f14006c7ed1f9577dfd3d61872fbbfe52ebff45fcbafaa3a5bfa635edfa8b6fa760ff577bfd2f7dffb97f7e75fd8da69ff1830ee8afffb5d75faef9d7ed91ecfaa3853f73778974fccdf07be07726602ffcb9895f5d7f99fc67abfee01bf17f1ee5cf21fd3d03fa87e93fbefe8db7230101c4f517f300ad3f9e3c295e474f80f8eb1e54e680f27b0fbfe8fcb7d2bc8f5e7cfdc976a0077e9703d2fad720f0f00b3fffd5b45ee3b738d039bfcb016d7e8f75b1fe9d4e19f4eaf587bafe4becff02fb1ff8fa934fbf182122facb0fbec63fd7df680146fbdff0c73ae0609f9de07640f6f9eb167e4f0708d4ffc65aeb8feee3cfedeb3faf0392f3efc4a2ffddf32ff63fb8fc92cf1fb65b0ffc3efdefbaff1bebdfaafebae93be167e8bfc40540f7bf859fbfeadd01b0fe13d87f666f40b4e92f107f04ffb4c11fafbf31f5471b7fa40b8eeb3f3bc1e549b7f35f4ffcd6eb9f791d90dc7f6dd15f1fbfe8fd476dfd8fe0efe3fe431ffa6b77a097f8eb365dd1ffbefbbfaeffbefd8fe1afbfa3d9651c80e347f7df65f6bf91f5377fffa15d7fa3f945ea8f2771559067f2e9a1fe57e6470a90b3a0bfb983bf870d7867fc9e0e10baff99c7f24bdc80aed47f2d0499d38191ccf347e6fed3ec6dda2800acfc42cf3fadee3f04172002dbbf3efd73d18bdd7f8d3611fd2bda595f8fa5175aff0af047eb9fbdff7d5b510dfe080f5c97dfc6df76ff61c67f741411bf53ff3c1d2052ffbb1cf0f0775cff7b1c90d43f1b7fc70b2070ff5beef75f22f557ecf9db56fe00fdc3ef7f2af393030715feeaac9305f0c3cf5fadd43f3c7e587f97e38fdbfd65fdb59c7f63e31f3bea3ffffe4787fbbf5e13d1df72fbb5b500f1de0912d25f5b0f4cf9fa7fc4f6c0a9ffecf84b63f263f5a7e6fe9b8cfee93e00a4fefb1f1e077cf58fc4f33ff3fdff567a3277fca8fe78eb0fab0372fc07083fbafe1dfbf4bf537e7ffd67e31fc9ac3ffdfc96f04775fd8fd5dfdcc36f61cf57eb8fb85d007ffd69e7175dff36f923f43f427f4d6366fe595b83f8b91eacaeffd6d6960ef8cca2ffac6180fcfd2919fdd3d65fdd07803cfcdefa5f60fde5e02f4ff13980ea9ff71650d7fa375f8069f1cf1a73ecffdb1c381270a0f2fc85167ff5fecf68340aeeffbafec7df7fa5b60e2625ffa895bf9dbec11fbdff3cce677fffab3d7e0b7b1b7f94fe9af27ba6bf35fa7cddc5dfa63f6c0766fcebeb9386fe97f2cbe58fd1dfbc1a7fbe22bf7c7ebefe56f9fdfabf2c4bacfc8c2d0044fe2af79f587dbe127f34bdd0fd2ff70d0037bddcfac342ef73406cffd1caef70416efe75f33bf4e714f147afff7c8fe074cb5f63afcb0f8f3ffefeeb41b9ff50fcdbaebfaefa4b40ff2afa3b5a71c049dfa2bfb1fa67fefe675bfc16f676fe88f56f957fb5fec85f7238d0ca1fa3bfe38afe33f865f437afe96f117f4d7e1bfcebeb01facb7060b5fe28f86b0e34e20fe167dc0370de7ff7589d9fd1e92df1b75bd608dfce1f39ff7be49fc11f3bff47dfff179a7ffdfadfe5fcefed7fbb030dfe98fd4fe7affff4c01f547f04f203ebbf7ca6c298fe47de7f2d1b2bf71f2cfa1fcc1f7fff3542ffdbe75fa603e3e5ffbfd1a2ffa43f36769bfef23c30f3bf9cfe73d7bfd5fe67f10be9ef32fe207e71fd5dad3f6a2ef4c06fedde9cb7feece2f91337bf8cfec5c72f34ff47ff0a840cbf2f7ebb07c2fae3e0ef52ff42e20fe58f58ff39cbef1ef89d05681ffcb5df7f85f5ff88fdfc53ee5affe6ae2d4011fd5dfeff1badfc0bf2e9b4b1312ca3bf35fe95fdff4afd315ddd1997dd7f6eeeff1bfe08fde7e96f3eef80f24da4fe88d0ff257fad0088e567ff1e40bb6d6c60f8298847f9b5fdd78effbcfbaf3d7ef4f1b9ffa44ef931fc791fbf43c76b8f9f84d7cd7fedf13374fea1e3b5fb4f3fff503c9abf9803faf1ebe2cffbf83beff10f3f7fcf77fe6beb9f365ebbff878f47f3573dff2107f4fb3fe1111bfefc31f8fc831ad8001bf8efa7d9e7a6103f00ce86af7fdafc91f8db5278fdf8d5f317d4cf5ef27707c45b4d3b7f078a17cbbf38fcaddb2fcc7f8af31fc1eface0b9e953c7b3b367bb4c85cafc85e52f8a47f32fe53f8657d27f9dfcdd7eb581e7f19bb18ee0b757f09cf4294ede46f2bf89e7e5ef34cf76eaf3074fbe8babb5534f455efe15f8ed51047e7b6764f9668e8f9e02b4f3571fafb2feace81703bf6d82ad8d7f0ebe25ff99f9d7c4332230644b3c2b7fc8d91d4a8525fe191f1fcd3fa5584bfcc6e2fab1f26fc1bfec7383773730cfff0d9a7f46edf84f03835831edfcc1f1baf74f58fc3bcd328e953e3baf363ee2e117e7c6e9df4633ffb9f9b38ae7e46f891fd5eb0f36ff8afe73f2b7ac352cf91fd2c0023f6dc1bbf37767e9bf2dff5f8c4a24edfc13c85fd5f51f2b7fdaf31fc6070700e2dbc60a33ff1a0d30f3df860fcddf62fea87f1699bf0b3f38fa3bc38f2cf81703f00bfd6fc347e6bf6efef69a7fedfcf0fd9bbef2cf860f0e00c56f34f1bcfcb7ce1f81f96bc787e56ff3b305fe153f7ed15191f95be2b7b35ad270f2b764ddb1f2e7cffc21348cb57eea008fee5f0ecaff96fc3b25f8b0261cf8a006c0fc6b338efe965973cf86f7e6ef2c6bef66d6fc0bc2df8ac65754df92ff117dd8d3fd8baef1d14df48adf6eeee2f69a7f5de223f79f58fa49ffd8f3372c7fee46e397f91b577fcff017ec785ffe4e3bc87f21fd1b46fe39f0b10d88e143ae9d63fe08c2bbf217e50fc9bf96cf58f9333b635a3d31423fa7f42717daf0cf02f11b597bfdeecbbf0a1ec9dfda32a6868f9a834f3c96f0099ff0a7177f3c70ff133ee1133e1e9ff23fe1137eb878347f7d0e9cf6f8133ee1878cd7cedf94ff099ff0f178347fd5f3dfe300489ff009df297ef0f9e769c08f77371080777601187ec2277ca778f5fc05f5d3e74100ded94008de1502e47cc227bcc7069fbf78fe43faeb6b2004efeac47864c227fc39c87fbc7e87f5db154310ded100e2fb79c06baf3fd5f307c57b22f0e371fd44f1b8fec6e79faf8140bcb50f6271a1f8733ffe51bc7afd8ae2f1fc75b9108407ea5f5f0861783c7f6d0d84e26d0d443b1ecaaf8d1f7cfea078547f61fd565dbffa1a08c40f367f7d0d7861d69eeb099ff20fc4c3fbcf285e75fdea6b20101f5d3ffb3c08c6c7e6af278478cfc3f9513cac1f281e1dbff0f8d7c60f3fff06abbf4b43f1ad0ec43333f0eae31f1dbff0f8d7c6a3f9a75fffa2784b03e1f801e72f8cb7747e303ee50f8887f54f1b8feb278a3fcff96b0f60fed5dd7d4e432b7ead6793fb77e2f185138f1f7e17c27ffcc8fff761ac767c927df4701c8f2fec5ff72178f608c43f7e08c13f79fc1284ff37d2fdc94e81dd03f2375bffe4f103207f8f4f9e82f9fbfc3f0f80fc3d3e598f07cbd84718fce9c713553c3a7f648f307832d410fda7f183cc1f94ff083be53f82cfd0fc6715615d18187f81ff0c84c7ae1fcd1f183e196ab75e43d0cfd7eebee03fcb6a70fe3e5fc3f068fe3fc5f019e8bf40feebe2b397417c32d02ed8fe07b12083c72f863f46f110bab0e7285eb7fff0fc07f99369dbf66711b4faf845f1181c36f5f853fe9e7783fe9b9dc1eb1f064f962c1960caf3c731cc0fe293254b166d68fe6ae393254b166fdaf9ab8e479f5f507ffe2159b2e19a7afe6be3c1f9431b9f2c1962f0f8d5cedf84d7c5a7f9eb7cdbc0f5131dff2709af8a4f960c3174fec0c73ff8fc278c87e0eaf864c9104bf90fc1d5f1c9922186d7ffdaf9ab9bff9aebb70b4bbb78e9caebd7ab8797ae5e3bac1eef1e5cbfb13cbeb4bbf7fae18dead77bd70e6f568ef7f6afdda81cefeeed5fbf71ab02dfbf7cfd66e5786ffff2e1e2f8e2c5fd2b07d76ebef1e6fce812f97678ebdb6f19aeddabd76fdc7ce3addbe670efa000bf79fb4e79f6dee52b570f0bf0ed3b6f97715cbe5ab6551cbe4d4ded5e3928da2a0fbfb3f9c75f5e285f7ff8c5b7367ff393af6dbeffc32f6d3eb8f7d5cd77bfff85cdf77ef0c5f2b3dffdec1be5f70f7fbd5b9efbd777f737ff7cffd2e69f7e75b13c36e77cf8e3af2cdee9f5c18fbe5cbe1b2c61e8e72a1f7d46c7bffde9d7cbf3e945bc744cdf932ff4fafdcfbfb938d7bce87b6a97380943af77bef75af939f94f6dd177f432fed2cfd577f283da270c9d6fb0f419f94efd41be5431745cf8b365e2228c899770e483698bdec95783233fe855e04abcf98c7888975ef4b3e1357dfa9777f6ca77ea076a6fde46796cda212e3a3631d3e7744ce7d1cf7f7bef72f9fac70757cb776a93aea56983de4dcce61ad2e7868bcefffbfb57ca9f291e3aa677131b9d6fae17e1e8736ad38c13c29a971947c607331e8cdf669cd08bce31e7198c39e79f1f1e2cf0c617e32bf94ded55fbdff48de977c2527f10c68c6bc29a18cd98a7cfcd982ce2dca297e91b83317d427d6bda32d7cbf46fd1c656c1bf55f4f196191b2646931f86db5c4bea4f3a97ae0b8d71e22ec618f9b0e0a88eadf978d82adad8227fcd18a7b6e6e3abc417afff0309a69f37";
			string test3 = "7801EDDC310D00000803B02508C0BF5B828A3DAD904E920900000000000000000000000000000000000000000000000000000000000000F016000000000000000000000000000000A86BFF03000000000000000000000000000000000000000000000000000000000000000040CF01072DC034";

			//$ordered = zlib_encode(
			//int chunkX) . 
			//int chunkZ) . 
			//$orderedIds . 
			//$orderedData . 
			//$orderedSkyLight .
			//$orderedLight . 
			//$this->biomeIds . 
			//$biomeColors . 
			//$this->tiles


			byte[] val = SoapHexBinary.Parse(test).Value;
			Assert.IsNotNull(val);


			MemoryStream stream = new MemoryStream(val);
			if (stream.ReadByte() != 0x78)
			{
				throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
			}
			stream.ReadByte();
			using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
			{
				NbtBinaryReader defStream = new NbtBinaryReader(defStream2, true);
				ChunkColumn chunk = new ChunkColumn();

				chunk.x = IPAddress.NetworkToHostOrder(defStream.ReadInt32());
				chunk.z = IPAddress.NetworkToHostOrder(defStream.ReadInt32());

				int chunkSize = 16*16*128;
				Assert.AreEqual(chunkSize, defStream.Read(chunk.blocks, 0, chunkSize));
				Assert.AreEqual(chunkSize/2, defStream.Read(chunk.metadata.Data, 0, chunkSize/2));
				Assert.AreEqual(chunkSize/2, defStream.Read(chunk.skylight.Data, 0, chunkSize/2));
				Assert.AreEqual(chunkSize/2, defStream.Read(chunk.blocklight.Data, 0, chunkSize/2));

				Assert.AreEqual(256, defStream.Read(chunk.biomeId, 0, 256));

				byte[] ints = new byte[256*4];
				Assert.AreEqual(ints.Length, defStream.Read(ints, 0, ints.Length));
				int j = 0;
				for (int i = 0; i < ints.Length; i = i + 4)
				{
					chunk.biomeColor[j++] = BitConverter.ToInt32(new[] {ints[i], ints[i + 1], ints[i + 2], ints[i + 3]}, 0);
				}

				MemoryStream uncompressed = new MemoryStream();
				int b = -1;
				do
				{
					b = defStream2.ReadByte();
					if (b != -1) uncompressed.WriteByte((byte) b);
				} while (b != -1);

				Assert.AreEqual(0, uncompressed.Length);
				//Assert.AreEqual(83208, uncompressed.Length);
				Assert.AreEqual(8, chunk.x);
				Assert.AreEqual(9, chunk.z);
				byte[] data = chunk.GetBytes();
				Assert.AreEqual(83208, data.Length); // Expected uncompressed length
			}
		}
Exemple #18
0
        public static ChunkColumn DecocedChunkColumn(byte[] buffer)
        {
            MemoryStream stream = new MemoryStream(buffer);
            {
                NbtBinaryReader defStream = new NbtBinaryReader(stream, true);
                ChunkColumn     chunk     = new ChunkColumn();

                //chunk.x = IPAddress.NetworkToHostOrder(defStream.ReadInt32());
                //chunk.z = IPAddress.NetworkToHostOrder(defStream.ReadInt32());

                int chunkSize = 16 * 16 * 128;
                defStream.Read(chunk.blocks, 0, chunkSize);
                defStream.Read(chunk.metadata.Data, 0, chunkSize / 2);
                defStream.Read(chunk.skylight.Data, 0, chunkSize / 2);
                defStream.Read(chunk.blocklight.Data, 0, chunkSize / 2);

                //Log.Debug($"skylight.Data:\n{Package.HexDump(chunk.skylight.Data, 64)}");
                //Log.Debug($"blocklight.Data:\n{Package.HexDump(chunk.blocklight.Data)}");

                defStream.Read(chunk.height, 0, 256);
                //Log.Debug($"Heights:\n{Package.HexDump(chunk.height)}");

                byte[] ints = new byte[256 * 4];
                defStream.Read(ints, 0, ints.Length);
                //Log.Debug($"biomeColor (pre):\n{Package.HexDump(ints)}");
                int j = 0;
                for (int i = 0; i < ints.Length; i = i + 4)
                {
                    chunk.biomeId[j]      = ints[i];
                    chunk.biomeColor[j++] = BitConverter.ToInt32(new[] { (byte)0, ints[i + 1], ints[i + 2], ints[i + 3] }, 0);
                }
                //Log.Debug($"biomeId (post):\n{Package.HexDump(chunk.biomeId)}");

                if (stream.Position >= stream.Length - 1)
                {
                    return(chunk);
                }

                //return chunk;

                int extraSize = defStream.ReadInt16();
                if (extraSize != 0)
                {
                    Log.Debug($"Got extradata\n{Package.HexDump(defStream.ReadBytes(extraSize))}");
                }

                if (stream.Position >= stream.Length - 1)
                {
                    return(chunk);
                }

                //Log.Debug($"Got NBT data\n{Package.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");

                while (stream.Position < stream.Length)
                {
                    NbtFile file = new NbtFile()
                    {
                        BigEndian = false, UseVarInt = true
                    };

                    file.LoadFromStream(stream, NbtCompression.None);

                    //Log.Debug($"Blockentity: {file.RootTag}");
                }

                return(chunk);
            }
        }
Exemple #19
0
 internal abstract void SkipTag(NbtBinaryReader readStream);
Exemple #20
0
        public static ChunkColumn DecocedChunkColumn(byte[] buffer)
        {
            lock (_chunkRead)
            {
                MemoryStream stream = new MemoryStream(buffer);
                {
                    NbtBinaryReader defStream = new NbtBinaryReader(stream, true);

                    Log.Debug("New chunk column");

                    int count = defStream.ReadByte();
                    if (count < 1)
                    {
                        Log.Warn("Nothing to read");
                        return(null);
                    }

                    if (count > 1)
                    {
                        Log.Debug($"Reading {count} sections");
                    }
                    else
                    {
                        Log.Debug($"Reading {count} sections");
                    }

                    ChunkColumn chunkColumn = new ChunkColumn();

                    for (int s = 0; s < count; s++)
                    {
                        int idx = defStream.ReadByte();

                        Log.Debug($"New section {s}, index={idx}");
                        Chunk chunk = chunkColumn.chunks[s];

                        int chunkSize = 16 * 16 * 16;
                        defStream.Read(chunk.blocks, 0, chunkSize);
                        //Log.Debug($"Blocks1:\n{Package.HexDump(chunk.blocks)}");

                        if (defStream.Read(chunk.metadata.Data, 0, chunkSize / 2) != chunkSize / 2)
                        {
                            Log.Error($"Out of data: metadata");
                        }

                        //Log.Debug($"metadata:\n{Package.HexDump(chunk.metadata.Data)}");

                        if (defStream.Read(chunk.skylight.Data, 0, chunkSize / 2) != chunkSize / 2)
                        {
                            Log.Error($"Out of data: skylight");
                        }
                        //Log.Debug($"skylight:\n{Package.HexDump(chunk.skylight.Data)}");

                        if (defStream.Read(chunk.blocklight.Data, 0, chunkSize / 2) != chunkSize / 2)
                        {
                            Log.Error($"Out of data: blocklight");
                        }
                        //Log.Debug($"blocklight:\n{Package.HexDump(chunk.blocklight.Data)}");

                        //Log.Debug($"skylight.Data:\n{Package.HexDump(chunk.skylight.Data, 64)}");
                        //Log.Debug($"blocklight.Data:\n{Package.HexDump(chunk.blocklight.Data)}");

                        //byte[] ints = new byte[256*4];
                        //var readLen = defStream.Read(ints, 0, ints.Length);
                        //if (readLen != ints.Length) Log.Error($"Out of data biomeColors, read lenght {readLen}");
                        //Log.Debug($"biomeColor (pre):\n{Package.HexDump(ints)}");

                        //return null;
                        //int j = 0;
                        //for (int i = 0; i < ints.Length; i = i + 4)
                        //{
                        //	chunk.biomeId[j] = ints[i];
                        //	chunk.biomeColor[j++] = BitConverter.ToInt32(new[] {(byte) 0, ints[i + 1], ints[i + 2], ints[i + 3]}, 0);
                        //}
                        //Log.Debug($"biomeId (post):\n{Package.HexDump(chunk.biomeId)}");

                        //if (stream.Position >= stream.Length - 1) return chunk;

                        ////return chunk;

                        //return chunk;
                    }

                    //if (stream.Position >= stream.Length - 1) continue;

                    if (defStream.Read(chunkColumn.height, 0, 256 * 2) != 256 * 2)
                    {
                        Log.Error($"Out of data height");
                    }
                    //Log.Debug($"Heights:\n{Package.HexDump(chunk.height)}");

                    //if (stream.Position >= stream.Length - 1) continue;

                    if (defStream.Read(chunkColumn.biomeId, 0, 256) != 256)
                    {
                        Log.Error($"Out of data biomeId");
                    }
                    //Log.Debug($"biomeId:\n{Package.HexDump(chunk.biomeId)}");

                    //if (stream.Position >= stream.Length - 1) continue;

                    int borderBlock = VarInt.ReadSInt32(stream);
                    if (borderBlock != 0)
                    {
                        Log.Warn($"??? Got borderblock {borderBlock}");
                    }

                    int extraCount = VarInt.ReadSInt32(stream);
                    if (extraCount != 0)
                    {
                        //Log.Warn($"Got extradata\n{Package.HexDump(defStream.ReadBytes(extraCount*10))}");
                        for (int i = 0; i < extraCount; i++)
                        {
                            var hash      = VarInt.ReadSInt32(stream);
                            var blockData = defStream.ReadInt16();
                            Log.Warn($"Got extradata: hash=0x{hash:X2}, blockdata=0x{blockData:X2}");
                        }
                    }

                    if (stream.Position < stream.Length - 1)
                    {
                        //Log.Debug($"Got NBT data\n{Package.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");

                        while (stream.Position < stream.Length)
                        {
                            NbtFile file = new NbtFile()
                            {
                                BigEndian = false, UseVarInt = true
                            };

                            file.LoadFromStream(stream, NbtCompression.None);

                            Log.Debug($"Blockentity: {file.RootTag}");
                        }
                    }
                    if (stream.Position < stream.Length - 1)
                    {
                        Log.Warn($"Still have data to read\n{Package.HexDump(defStream.ReadBytes((int)(stream.Length - stream.Position)))}");
                    }
                }

                return(new ChunkColumn());
            }
        }
Exemple #21
0
 internal override void SkipTag(NbtBinaryReader readStream)
 {
     readStream.SkipString();
 }
Exemple #22
0
 internal abstract bool ReadTag(NbtBinaryReader readStream);
        internal void HandlePackage(Package message, PlayerNetworkSession playerSession)
        {
            Player player = playerSession.Player;

            if (message == null)
            {
                return;
            }

            if (typeof(McpeWrapper) == message.GetType())
            {
                McpeWrapper batch = (McpeWrapper)message;

                // Get bytes
                byte[] payload = batch.payload;
                if (playerSession.CryptoContext != null && Config.GetProperty("UseEncryption", true))
                {
                    payload = CryptoUtils.Decrypt(payload, playerSession.CryptoContext);
                }

                //if (Log.IsDebugEnabled)
                //	Log.Debug($"0x{payload[0]:x2}\n{Package.HexDump(payload)}");

                var msg = PackageFactory.CreatePackage(payload[0], payload, "mcpe") ?? new UnknownPackage(payload[0], payload);
                HandlePackage(msg, playerSession);
                msg.PutPool();

                return;
            }

            if (typeof(UnknownPackage) == message.GetType())
            {
                UnknownPackage packet = (UnknownPackage)message;
                Log.Warn($"Received unknown package 0x{message.Id:X2}\n{Package.HexDump(packet.Message)}");

                return;
            }

            if (typeof(McpeBatch) == message.GetType())
            {
                Log.Debug("Handle MCPE batch message");
                McpeBatch batch = (McpeBatch)message;

                var messages = new List <Package>();

                // Get bytes
                byte[] payload = batch.payload;
                // Decompress bytes

                MemoryStream stream = new MemoryStream(payload);
                if (stream.ReadByte() != 0x78)
                {
                    throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
                }
                stream.ReadByte();
                using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
                {
                    // Get actual package out of bytes
                    MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream();
                    defStream2.CopyTo(destination);
                    destination.Position = 0;
                    NbtBinaryReader reader = new NbtBinaryReader(destination, true);

                    while (destination.Position < destination.Length)
                    {
                        int    len            = reader.ReadInt32();
                        byte[] internalBuffer = reader.ReadBytes(len);

                        //if (Log.IsDebugEnabled)
                        //	Log.Debug($"0x{internalBuffer[0]:x2}\n{Package.HexDump(internalBuffer)}");

                        messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer, "mcpe") ?? new UnknownPackage(internalBuffer[0], internalBuffer));
                    }

                    if (destination.Length > destination.Position)
                    {
                        throw new Exception("Have more data");
                    }
                }
                foreach (var msg in messages)
                {
                    msg.DatagramSequenceNumber = batch.DatagramSequenceNumber;
                    msg.OrderingChannel        = batch.OrderingChannel;
                    msg.OrderingIndex          = batch.OrderingIndex;
                    HandlePackage(msg, playerSession);
                    msg.PutPool();
                }

                return;
            }

            if (player != null)
            {
                player.HandlePackage(message);
            }
        }
Exemple #24
0
        public static ChunkColumn DecocedChunkColumn(byte[] buffer)
        {
            lock (_chunkRead)
            {
                MemoryStream stream = new MemoryStream(buffer);
                {
                    NbtBinaryReader defStream = new NbtBinaryReader(stream, true);

                    Log.Debug("New chunk column");

                    int count = defStream.ReadByte();
                    if (count < 1)
                    {
                        Log.Warn("Nothing to read");
                        return(null);
                    }

                    Log.Debug($"Reading {count} sections");

                    ChunkColumn chunkColumn = new ChunkColumn();

                    for (int s = 0; s < count; s++)
                    {
                        int version     = defStream.ReadByte();
                        int storageSize = defStream.ReadByte();

                        for (int i = 0; i < storageSize; i++)
                        {
                            int bitsPerBlock    = defStream.ReadByte() >> 1;
                            int noBlocksPerWord = (int)Math.Floor(32f / bitsPerBlock);
                            int wordCount       = (int)Math.Ceiling(4096f / noBlocksPerWord);
                            Log.Warn($"New section {s}, " +
                                     $"version={version}, " +
                                     $"storageSize={storageSize}, " +
                                     $"bitsPerBlock={bitsPerBlock}, " +
                                     $"noBlocksPerWord={noBlocksPerWord}, " +
                                     $"wordCount={wordCount}, " +
                                     $"");
                            defStream.ReadBytes(wordCount * 4);
                            int paletteCount = VarInt.ReadSInt32(stream);
                            //Log.Warn($"New section {s}, " +
                            //		$"version={version}, " +
                            //		$"storageSize={storageSize}, " +
                            //		$"bitsPerBlock={bitsPerBlock}, " +
                            //		$"noBlocksPerWord={noBlocksPerWord}, " +
                            //		$"wordCount={wordCount}, " +
                            //		$"paletteCount={paletteCount}" +
                            //		$"");

                            for (int j = 0; j < paletteCount; j++)
                            {
                                VarInt.ReadSInt32(stream);
                            }
                        }
                    }

                    //if (stream.Position >= stream.Length - 1) continue;

                    byte[] ba = new byte[512];
                    if (defStream.Read(ba, 0, 256 * 2) != 256 * 2)
                    {
                        Log.Error($"Out of data height");
                    }

                    Buffer.BlockCopy(ba, 0, chunkColumn.height, 0, 512);
                    //Log.Debug($"Heights:\n{Package.HexDump(ba)}");

                    //if (stream.Position >= stream.Length - 1) continue;

                    if (defStream.Read(chunkColumn.biomeId, 0, 256) != 256)
                    {
                        Log.Error($"Out of data biomeId");
                    }
                    //Log.Debug($"biomeId:\n{Package.HexDump(chunk.biomeId)}");

                    if (stream.Position >= stream.Length - 1)
                    {
                        return(chunkColumn);
                    }

                    int borderBlock = VarInt.ReadSInt32(stream);
                    if (borderBlock != 0)
                    {
                        byte[] buf = new byte[borderBlock];
                        int    len = defStream.Read(buf, 0, borderBlock);
                        Log.Warn($"??? Got borderblock {borderBlock}. Read {len} bytes");
                        Log.Debug($"{Packet.HexDump(buf)}");
                        for (int i = 0; i < borderBlock; i++)
                        {
                            int x = (buf[i] & 0xf0) >> 4;
                            int z = buf[i] & 0x0f;
                            Log.Debug($"x={x}, z={z}");
                        }
                    }

                    if (stream.Position < stream.Length - 1)
                    {
                        //Log.Debug($"Got NBT data\n{Package.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");

                        while (stream.Position < stream.Length)
                        {
                            NbtFile file = new NbtFile()
                            {
                                BigEndian = false,
                                UseVarInt = true
                            };

                            file.LoadFromStream(stream, NbtCompression.None);

                            Log.Debug($"Blockentity: {file.RootTag}");
                        }
                    }
                    if (stream.Position < stream.Length - 1)
                    {
                        Log.Warn($"Still have data to read\n{Packet.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");
                    }

                    return(chunkColumn);
                }
            }
        }
Exemple #25
0
        internal override bool ReadTag(NbtBinaryReader readStream)
        {
            if (Parent != null && readStream.Selector != null && !readStream.Selector(this))
            {
                SkipTag(readStream);
                return(false);
            }

            while (true)
            {
                NbtTagType nextTag = readStream.ReadTagType();
                NbtTag     newTag;
                switch (nextTag)
                {
                case NbtTagType.End:
                    return(true);

                case NbtTagType.Byte:
                    newTag = new NbtByte();
                    break;

                case NbtTagType.Short:
                    newTag = new NbtShort();
                    break;

                case NbtTagType.Int:
                    newTag = new NbtInt();
                    break;

                case NbtTagType.Long:
                    newTag = new NbtLong();
                    break;

                case NbtTagType.Float:
                    newTag = new NbtFloat();
                    break;

                case NbtTagType.Double:
                    newTag = new NbtDouble();
                    break;

                case NbtTagType.ByteArray:
                    newTag = new NbtByteArray();
                    break;

                case NbtTagType.String:
                    newTag = new NbtString();
                    break;

                case NbtTagType.List:
                    newTag = new NbtList();
                    break;

                case NbtTagType.Compound:
                    newTag = new NbtCompound();
                    break;

                case NbtTagType.IntArray:
                    newTag = new NbtIntArray();
                    break;

                default:
                    throw new NbtFormatException("Unsupported tag type found in NBT_Compound: " + nextTag);
                }
                newTag.Parent = this;
                newTag.Name   = readStream.ReadString();
                if (newTag.ReadTag(readStream))
                {
                    // ReSharper disable AssignNullToNotNullAttribute
                    // newTag.Name is never null
                    tags.Add(newTag.Name, newTag);
                    // ReSharper restore AssignNullToNotNullAttribute
                }
            }
        }
Exemple #26
0
        private void OnBatch(Package message)
        {
            McpeBatch batch = (McpeBatch) message;

            var messages = new List<Package>();

            // Get bytes
            byte[] payload = batch.payload;
            // Decompress bytes

            MemoryStream stream = new MemoryStream(payload);
            if (stream.ReadByte() != 0x78)
            {
                throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
            }
            stream.ReadByte();
            using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
            {
                // Get actual package out of bytes
                MemoryStream destination = new MemoryStream();
                defStream2.CopyTo(destination);
                destination.Position = 0;
                NbtBinaryReader reader = new NbtBinaryReader(destination, true);
                do
                {
                    int len = reader.ReadInt32();
                    byte[] internalBuffer = reader.ReadBytes(len);
                    messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer) ?? new UnknownPackage(internalBuffer[0], internalBuffer));
                } while (destination.Position < destination.Length);
            }
            foreach (var msg in messages)
            {
                msg.DatagramSequenceNumber = batch.DatagramSequenceNumber;
                msg.OrderingChannel = batch.OrderingChannel;
                msg.OrderingIndex = batch.OrderingIndex;
                HandlePackage(msg);
                msg.PutPool();
            }
        }
Exemple #27
0
        internal override void SkipTag(NbtBinaryReader readStream)
        {
            while (true)
            {
                NbtTagType nextTag = readStream.ReadTagType();
                NbtTag     newTag;
                switch (nextTag)
                {
                case NbtTagType.End:
                    return;

                case NbtTagType.Byte:
                    newTag = new NbtByte();
                    break;

                case NbtTagType.Short:
                    newTag = new NbtShort();
                    break;

                case NbtTagType.Int:
                    newTag = new NbtInt();
                    break;

                case NbtTagType.Long:
                    newTag = new NbtLong();
                    break;

                case NbtTagType.Float:
                    newTag = new NbtFloat();
                    break;

                case NbtTagType.Double:
                    newTag = new NbtDouble();
                    break;

                case NbtTagType.ByteArray:
                    newTag = new NbtByteArray();
                    break;

                case NbtTagType.String:
                    newTag = new NbtString();
                    break;

                case NbtTagType.List:
                    newTag = new NbtList();
                    break;

                case NbtTagType.Compound:
                    newTag = new NbtCompound();
                    break;

                case NbtTagType.IntArray:
                    newTag = new NbtIntArray();
                    break;

                default:
                    throw new NbtFormatException("Unsupported tag type found in NBT_Compound: " + nextTag);
                }
                readStream.SkipString();
                newTag.SkipTag(readStream);
            }
        }
Exemple #28
0
        protected void DecodeCert(McpeLogin message)
        {
            byte[] buffer = message.payload;

            if (message.payload.Length != buffer.Length)
            {
                Log.Debug($"Wrong lenght {message.payload.Length} != {message.payload.Length}");
                throw new Exception($"Wrong lenght {message.payload.Length} != {message.payload.Length}");
            }

            if (Log.IsDebugEnabled)
            {
                Log.Debug("Lenght: " + message.payload.Length + ", Message: " + Convert.ToBase64String(buffer));
            }

            string certificateChain;
            string skinData;

            try
            {
                var destination = new MemoryStream(buffer);
                destination.Position = 0;
                NbtBinaryReader reader = new NbtBinaryReader(destination, false);

                var countCertData = reader.ReadInt32();
                certificateChain = Encoding.UTF8.GetString(reader.ReadBytes(countCertData));
                if (Log.IsDebugEnabled)
                {
                    Log.Debug($"Certificate Chain (Lenght={countCertData})\n{certificateChain}");
                }

                var countSkinData = reader.ReadInt32();
                skinData = Encoding.UTF8.GetString(reader.ReadBytes(countSkinData));
                if (Log.IsDebugEnabled)
                {
                    Log.Debug($"Skin data (Lenght={countSkinData})\n{skinData}");
                }
            }
            catch (Exception e)
            {
                Log.Error("Parsing login", e);
                return;
            }

            try
            {
                {
                    IDictionary <string, dynamic> headers = JWT.Headers(skinData);
                    dynamic payload = JObject.Parse(JWT.Payload(skinData));

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Skin JWT Header: {string.Join(";", headers)}");
                    }
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Skin JWT Payload:\n{payload.ToString()}");
                    }

                    try
                    {
                        _playerInfo.ClientId         = payload.ClientRandomId;
                        _playerInfo.CurrentInputMode = payload.CurrentInputMode;
                        _playerInfo.DefaultInputMode = payload.DefaultInputMode;
                        _playerInfo.DeviceModel      = payload.DeviceModel;
                        _playerInfo.DeviceOS         = payload.DeviceOS;
                        _playerInfo.GameVersion      = payload.GameVersion;
                        _playerInfo.GuiScale         = payload.GuiScale;
                        _playerInfo.LanguageCode     = payload.LanguageCode;
                        _playerInfo.ServerAddress    = payload.ServerAddress;
                        _playerInfo.UIProfile        = payload.UIProfile;

                        _playerInfo.Skin = new Skin()
                        {
                            CapeData         = Convert.FromBase64String((string)payload.CapeData),
                            SkinId           = payload.SkinId,
                            SkinData         = Convert.FromBase64String((string)payload.SkinData),
                            SkinGeometryName = payload.SkinGeometryName,
                            SkinGeometry     = Convert.FromBase64String((string)payload.SkinGeometry),
                        };
                        Log.Warn($"Cape data lenght={_playerInfo.Skin.CapeData.Length}");
                    }
                    catch (Exception e)
                    {
                        Log.Error("Parsing skin data", e);
                    }
                }

                {
                    dynamic json = JObject.Parse(certificateChain);

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Certificate JSON:\n{json}");
                    }

                    JArray chain = json.chain;
                    //var chainArray = chain.ToArray();

                    string validationKey     = null;
                    string identityPublicKey = null;

                    foreach (JToken token in chain)
                    {
                        IDictionary <string, dynamic> headers = JWT.Headers(token.ToString());

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug("Raw chain element:\n" + token.ToString());
                            Log.Debug($"JWT Header: {string.Join(";", headers)}");

                            dynamic jsonPayload = JObject.Parse(JWT.Payload(token.ToString()));
                            Log.Debug($"JWT Payload:\n{jsonPayload}");
                        }

                        // Mojang root x5u cert (string): MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V

                        if (!headers.ContainsKey("x5u"))
                        {
                            continue;
                        }

                        string x5u = headers["x5u"];

                        if (identityPublicKey == null)
                        {
                            if (CertificateData.MojangRootKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase))
                            {
                                Log.Debug("Key is ok, and got Mojang root");
                            }
                            else if (chain.Count > 1)
                            {
                                Log.Debug("Got client cert (client root)");
                                continue;
                            }
                            else if (chain.Count == 1)
                            {
                                Log.Debug("Selfsigned chain");
                            }
                        }
                        else if (identityPublicKey.Equals(x5u))
                        {
                            Log.Debug("Derived Key is ok");
                        }

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug($"x5u cert (string): {x5u}");
                            ECDiffieHellmanPublicKey publicKey = CryptoUtils.CreateEcDiffieHellmanPublicKey(x5u);
                            Log.Debug($"Cert:\n{publicKey.ToXmlString()}");
                        }

                        // Validate
                        CngKey          newKey = CryptoUtils.ImportECDsaCngKeyFromString(x5u);
                        CertificateData data   = JWT.Decode <CertificateData>(token.ToString(), newKey);

                        if (data != null)
                        {
                            identityPublicKey = data.IdentityPublicKey;

                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug("Decoded token success");
                            }

                            if (CertificateData.MojangRootKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase))
                            {
                                Log.Debug("Got Mojang key. Is valid = " + data.CertificateAuthority);
                                validationKey = data.IdentityPublicKey;
                            }
                            else if (validationKey != null && validationKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase))
                            {
                                _playerInfo.CertificateData = data;
                            }
                            else
                            {
                                if (data.ExtraData == null)
                                {
                                    continue;
                                }

                                // Self signed, make sure they don't fake XUID
                                if (data.ExtraData.Xuid != null)
                                {
                                    Log.Warn("Received fake XUID from " + data.ExtraData.DisplayName);
                                    data.ExtraData.Xuid = null;
                                }

                                _playerInfo.CertificateData = data;
                            }
                        }
                        else
                        {
                            Log.Error("Not a valid Identity Public Key for decoding");
                        }
                    }

                    //TODO: Implement disconnect here

                    {
                        _playerInfo.Username = _playerInfo.CertificateData.ExtraData.DisplayName;
                        _session.Username    = _playerInfo.Username;
                        string identity = _playerInfo.CertificateData.ExtraData.Identity;

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug($"Connecting user {_playerInfo.Username} with identity={identity}");
                        }
                        _playerInfo.ClientUuid = new UUID(identity);

                        _session.CryptoContext = new CryptoContext
                        {
                            UseEncryption = Config.GetProperty("UseEncryptionForAll", false) || (Config.GetProperty("UseEncryption", true) && !string.IsNullOrWhiteSpace(_playerInfo.CertificateData.ExtraData.Xuid)),
                        };

                        if (_session.CryptoContext.UseEncryption)
                        {
                            ECDiffieHellmanPublicKey publicKey = CryptoUtils.CreateEcDiffieHellmanPublicKey(_playerInfo.CertificateData.IdentityPublicKey);
                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug($"Cert:\n{publicKey.ToXmlString()}");
                            }

                            // Create shared shared secret
                            ECDiffieHellmanCng ecKey = new ECDiffieHellmanCng(384);
                            ecKey.HashAlgorithm         = CngAlgorithm.Sha256;
                            ecKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                            ecKey.SecretPrepend         = Encoding.UTF8.GetBytes("RANDOM SECRET");                     // Server token

                            byte[] secret = ecKey.DeriveKeyMaterial(publicKey);

                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug($"SECRET KEY (b64):\n{Convert.ToBase64String(secret)}");
                            }

                            {
                                RijndaelManaged rijAlg = new RijndaelManaged
                                {
                                    BlockSize    = 128,
                                    Padding      = PaddingMode.None,
                                    Mode         = CipherMode.CFB,
                                    FeedbackSize = 8,
                                    Key          = secret,
                                    IV           = secret.Take(16).ToArray(),
                                };

                                // Create a decrytor to perform the stream transform.
                                ICryptoTransform decryptor      = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
                                MemoryStream     inputStream    = new MemoryStream();
                                CryptoStream     cryptoStreamIn = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read);

                                ICryptoTransform encryptor       = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
                                MemoryStream     outputStream    = new MemoryStream();
                                CryptoStream     cryptoStreamOut = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write);

                                _session.CryptoContext.Algorithm       = rijAlg;
                                _session.CryptoContext.Decryptor       = decryptor;
                                _session.CryptoContext.Encryptor       = encryptor;
                                _session.CryptoContext.InputStream     = inputStream;
                                _session.CryptoContext.OutputStream    = outputStream;
                                _session.CryptoContext.CryptoStreamIn  = cryptoStreamIn;
                                _session.CryptoContext.CryptoStreamOut = cryptoStreamOut;
                            }

                            //TODO: JSON now.
                            throw new Exception("JSON!!!");
                            //var response = McpeServerToClientHandshake.CreateObject();
                            //	response.NoBatch = true;
                            //	response.ForceClear = true;

                            //response.token =
                            //	response.serverPublicKey = Convert.ToBase64String(ecKey.PublicKey.GetDerEncoded());
                            //	response.tokenLength = (short) ecKey.SecretPrepend.Length;
                            //	response.token = ecKey.SecretPrepend;

                            //_session.SendPackage(response);

                            if (Log.IsDebugEnabled)
                            {
                                Log.Warn($"Encryption enabled for {_session.Username}");
                            }
                        }
                    }
                }

                if (!_session.CryptoContext.UseEncryption)
                {
                    _session.MessageHandler.HandleMcpeClientToServerHandshake(null);
                }
            }
            catch (Exception e)
            {
                Log.Error("Decrypt", e);
            }
        }
Exemple #29
0
        /// <summary>
        ///     Handles the specified package.
        /// </summary>
        /// <param name="message">The package.</param>
        /// <param name="senderEndpoint">The sender's endpoint.</param>
        private void HandlePackage(Package message, IPEndPoint senderEndpoint)
        {
            if (typeof(McpeBatch) == message.GetType())
            {
                Log.Debug("Processing Batch package");
                McpeBatch batch = (McpeBatch)message;

                var messages = new List <Package>();

                // Get bytes
                byte[] payload = batch.payload;
                // Decompress bytes

                MemoryStream stream = new MemoryStream(payload);
                if (stream.ReadByte() != 0x78)
                {
                    throw new InvalidDataException("Incorrect ZLib header. Expected 0x78");
                }
                stream.ReadByte();
                using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
                {
                    // Get actual package out of bytes
                    MemoryStream destination = new MemoryStream();
                    defStream2.CopyTo(destination);
                    destination.Position = 0;
                    NbtBinaryReader reader = new NbtBinaryReader(destination, true);
                    do
                    {
                        int    len            = reader.ReadInt32();
                        byte[] internalBuffer = reader.ReadBytes(len);
                        messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer) ?? new UnknownPackage(internalBuffer[0], internalBuffer));
                    } while (destination.Position < destination.Length);                     // throw new Exception("Have more data");
                }
                foreach (var msg in messages)
                {
                    HandlePackage(msg, senderEndpoint);
                    msg.PutPool();
                }
                return;
            }

            TraceReceive(message);

            if (typeof(UnknownPackage) == message.GetType())
            {
                return;
            }

            if (typeof(McpeDisconnect) == message.GetType())
            {
                McpeDisconnect msg = (McpeDisconnect)message;
                Log.InfoFormat("Disconnect {1}: {0}", msg.message, Username);
                SendDisconnectionNotification();
                StopClient();
                return;
            }

            if (typeof(ConnectedPing) == message.GetType())
            {
                ConnectedPing msg = (ConnectedPing)message;
                SendConnectedPong(msg.sendpingtime);
                return;
            }

            if (typeof(McpeFullChunkData) == message.GetType())
            {
                //McpeFullChunkData msg = (McpeFullChunkData) message;
                //ChunkColumn chunk = ClientUtils.DecocedChunkColumn(msg.chunkData);
                //if (chunk != null)
                //{
                //	Log.DebugFormat("Chunk X={0}", chunk.x);
                //	Log.DebugFormat("Chunk Z={0}", chunk.z);

                //	//ClientUtils.SaveChunkToAnvil(chunk);
                //}
                return;
            }

            if (typeof(ConnectionRequestAccepted) == message.GetType())
            {
                Thread.Sleep(50);
                SendNewIncomingConnection();
                //_connectedPingTimer = new Timer(state => SendConnectedPing(), null, 1000, 1000);
                Thread.Sleep(50);
                SendLogin(Username);
                return;
            }

            if (typeof(McpeSetSpawnPosition) == message.GetType())
            {
                McpeSetSpawnPosition msg = (McpeSetSpawnPosition)message;
                _spawn        = new Vector3(msg.x, msg.y, msg.z);
                _level.SpawnX = (int)_spawn.X;
                _level.SpawnY = (int)_spawn.Y;
                _level.SpawnZ = (int)_spawn.Z;

                return;
            }

            if (typeof(McpeStartGame) == message.GetType())
            {
                McpeStartGame msg = (McpeStartGame)message;
                _entityId        = msg.entityId;
                _spawn           = new Vector3(msg.x, msg.y, msg.z);
                _level.LevelName = "Default";
                _level.Version   = 19133;
                _level.GameType  = msg.gamemode;

                //ClientUtils.SaveLevel(_level);

                return;
            }

            if (typeof(McpeTileEvent) == message.GetType())
            {
                McpeTileEvent msg = (McpeTileEvent)message;
                Log.DebugFormat("X: {0}", msg.x);
                Log.DebugFormat("Y: {0}", msg.y);
                Log.DebugFormat("Z: {0}", msg.z);
                Log.DebugFormat("Case 1: {0}", msg.case1);
                Log.DebugFormat("Case 2: {0}", msg.case2);
                return;
            }
            if (typeof(McpeAddEntity) == message.GetType())
            {
                McpeAddEntity msg = (McpeAddEntity)message;
                Log.DebugFormat("Entity ID: {0}", msg.entityId);
                Log.DebugFormat("Entity Type: {0}", msg.entityType);
                Log.DebugFormat("X: {0}", msg.x);
                Log.DebugFormat("Y: {0}", msg.y);
                Log.DebugFormat("Z: {0}", msg.z);
                Log.DebugFormat("Yaw: {0}", msg.yaw);
                Log.DebugFormat("Pitch: {0}", msg.pitch);
                Log.DebugFormat("Velocity X: {0}", msg.speedX);
                Log.DebugFormat("Velocity Y: {0}", msg.speedY);
                Log.DebugFormat("Velocity Z: {0}", msg.speedZ);
                //Log.DebugFormat("Metadata: {0}", msg.metadata.ToString());
                //Log.DebugFormat("Links count: {0}", msg.links);

                return;
            }
            if (typeof(McpeSetEntityData) == message.GetType())
            {
                McpeSetEntityData msg = (McpeSetEntityData)message;
                Log.DebugFormat("Entity ID: {0}", msg.entityId);
                MetadataDictionary metadata = msg.metadata;
                Log.DebugFormat("Metadata: {0}", metadata.ToString());
                return;
            }

            if (typeof(McpeMovePlayer) == message.GetType())
            {
                //McpeMovePlayer msg = (McpeMovePlayer) message;
                //Log.DebugFormat("Entity ID: {0}", msg.entityId);

                //CurrentLocation = new PlayerLocation(msg.x, msg.y + 10, msg.z);
                //SendMcpeMovePlayer();
                return;
            }

            if (typeof(McpeUpdateBlock) == message.GetType())
            {
                McpeUpdateBlock msg = (McpeUpdateBlock)message;
                Log.DebugFormat("No of Blocks: {0}", msg.blocks.Count);
                return;
            }

            if (typeof(McpeLevelEvent) == message.GetType())
            {
                McpeLevelEvent msg = (McpeLevelEvent)message;
                Log.DebugFormat("Event ID: {0}", msg.eventId);
                Log.DebugFormat("X: {0}", msg.x);
                Log.DebugFormat("Y: {0}", msg.y);
                Log.DebugFormat("Z: {0}", msg.z);
                Log.DebugFormat("Data: {0}", msg.data);
                return;
            }

            if (typeof(McpeContainerSetContent) == message.GetType())
            {
                McpeContainerSetContent msg = (McpeContainerSetContent)message;
                Log.DebugFormat("Window ID: 0x{0:x2}, Count: {1}", msg.windowId, msg.slotData.Count);
                var slots = msg.slotData.GetValues();

                foreach (var entry in slots)
                {
                    MetadataSlot slot = (MetadataSlot)entry;
                    //Log.DebugFormat(" - Id: {0}, Metadata: {1}, Count: {2}", slot.Value.Item.Id, slot.Value.Item.Metadata, slot.Value.Count);
                }
                return;
            }

            if (typeof(McpeCraftingData) == message.GetType())
            {
                string fileName = Path.GetTempPath() + "Recipes_" + Guid.NewGuid() + ".txt";
                Log.Info("Writing recipes to filename: " + fileName);
                FileStream file = File.OpenWrite(fileName);

                McpeCraftingData   msg    = (McpeCraftingData)message;
                IndentedTextWriter writer = new IndentedTextWriter(new StreamWriter(file));

                writer.WriteLine("static RecipeManager()");
                writer.WriteLine("{");
                writer.Indent++;
                writer.WriteLine("Recipes = new Recipes");
                writer.WriteLine("{");
                writer.Indent++;

                foreach (Recipe recipe in msg.recipes)
                {
                    ShapelessRecipe shapelessRecipe = recipe as ShapelessRecipe;
                    if (shapelessRecipe != null)
                    {
                        writer.WriteLine(string.Format("new ShapelessRecipe(new ItemStack(ItemFactory.GetItem({0}, {1}), {2}),", shapelessRecipe.Result.Id, shapelessRecipe.Result.Metadata, shapelessRecipe.Result.Count));
                        writer.Indent++;
                        writer.WriteLine("new List<ItemStack>");
                        writer.WriteLine("{");
                        writer.Indent++;
                        foreach (var itemStack in shapelessRecipe.Input)
                        {
                            writer.WriteLine(string.Format("new ItemStack(ItemFactory.GetItem({0}, {1}), {2}),", itemStack.Id, itemStack.Metadata, itemStack.Count));
                        }
                        writer.Indent--;
                        writer.WriteLine("}),");
                        writer.Indent--;

                        continue;
                    }

                    ShapedRecipe shapedRecipe = recipe as ShapedRecipe;
                    if (shapedRecipe != null)
                    {
                        writer.WriteLine(string.Format("new ShapedRecipe({0}, {1}, new ItemStack(ItemFactory.GetItem({2}, {3}), {4}),", shapedRecipe.Width, shapedRecipe.Height, shapedRecipe.Result.Id, shapedRecipe.Result.Metadata, shapedRecipe.Result.Count));
                        writer.Indent++;
                        writer.WriteLine("new Item[]");
                        writer.WriteLine("{");
                        writer.Indent++;
                        foreach (Item item in shapedRecipe.Input)
                        {
                            writer.WriteLine(string.Format("ItemFactory.GetItem({0}, {1}),", item.Id, item.Metadata));
                        }
                        writer.Indent--;
                        writer.WriteLine("}),");
                        writer.Indent--;

                        continue;
                    }
                }

                writer.WriteLine("};");
                writer.Indent--;
                writer.WriteLine("}");
                writer.Indent--;

                writer.Flush();

                file.Close();
                Environment.Exit(0);
                return;
            }
        }
 internal override void SkipTag(NbtBinaryReader readStream)
 {
     readStream.SkipString();
 }
Exemple #31
0
 internal override bool ReadTag(NbtBinaryReader readStream)
 {
     if (readStream.Selector != null && !readStream.Selector(this))
     {
         readStream.ReadByte();
         return false;
     }
     Value = readStream.ReadByte();
     return true;
 }
        protected void DecodeCert(McpeLogin message)
        {
            // Get bytes
            byte[] buffer = message.payload;

            //Log.Debug($"Unknown byte in login packet is: {message.unknown}");

            if (message.payload.Length != buffer.Length)
            {
                Log.Debug($"Wrong lenght {message.payload.Length} != {message.payload.Length}");
                throw new Exception($"Wrong lenght {message.payload.Length} != {message.payload.Length}");
            }
            // Decompress bytes

            Log.Debug("Lenght: " + message.payload.Length + ", Message: " + Convert.ToBase64String(buffer));

            //MemoryStream stream = new MemoryStream(buffer);
            //if (stream.ReadByte() != 0x78)
            //{
            //	throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
            //}
            //stream.ReadByte();

            string certificateChain;
            string skinData;

            //using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
            {
                // Get actual package out of bytes
                //using (MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream())
                {
                    //defStream2.CopyTo(destination);

                    var destination = new MemoryStream(buffer);
                    destination.Position = 0;
                    NbtBinaryReader reader = new NbtBinaryReader(destination, false);

                    try
                    {
                        var countCertData = reader.ReadInt32();
                        Log.Debug("Count cert: " + countCertData);
                        certificateChain = Encoding.UTF8.GetString(reader.ReadBytes(countCertData));
                        Log.Debug("Decompressed certificateChain " + certificateChain);

                        var countSkinData = reader.ReadInt32();
                        Log.Debug("Count skin: " + countSkinData);
                        skinData = Encoding.UTF8.GetString(reader.ReadBytes(countSkinData));
                        Log.Debug("Decompressed skinData" + skinData);
                    }
                    catch (Exception e)
                    {
                        Log.Error("Parsing login", e);
                        return;
                    }
                }
            }


            try
            {
                {
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug("Input SKIN string: " + skinData);
                    }

                    IDictionary <string, dynamic> headers = JWT.Headers(skinData);
                    dynamic payload = JObject.Parse(JWT.Payload(skinData));

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Skin JWT Header: {string.Join(";", headers)}");
                    }
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Skin JWT Payload:\n{payload.ToString()}");
                    }

                    Console.WriteLine(payload);
                    // Skin JWT Payload:

                    //{
                    //	"ClientRandomId": 1423700530444426768,
                    //	"CurrentInputMode": 1,
                    //	"DefaultInputMode": 1,
                    //	"DeviceModel": "ASUSTeK COMPUTER INC. N550JK",
                    //	"DeviceOS": 7,
                    //	"GameVersion": "1.2.0",
                    //	"GuiScale": 0,
                    //	"LanguageCode": "en_US",
                    //	"ServerAddress": "192.168.0.3:19132",
                    //	"SkinData": "SnNH/1+KUf97n2T/AAAAAAAAAAAAAAAAAAAAAAAAAACWlY//q6ur/5aVj/+WlY//q6ur/5aVj/+WlY//q6ur/1JSUv9zbmr/c25q/1JSUv9zbmr/UlJS/3Nuav9zbmr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBfQ/+WlY//q6ur/7+/v/8AAAAAAAAAAAAAAAAAAAAAQF9D/0pzR/9filH/SnNH/0BfQ/9Kc0f/SnNH/0BfQ/9zbmr/c25q/3Nuav9SUlL/c25q/1JSUv9zbmr/c25q/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7Sz7/c25q/1QxKP9wTTr/jGVJ/wAAAAAAAAAAAAAAAEpzR/9Kc0f/X4pR/1+KUf9Kc0f/SnNH/1+KUf9Kc0f/UlJS/1JSUv9SUlL/UlJS/1JSUv9SUlL/UlJS/3Nuav8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJSUv87IBz/AAAAAAAAAAAAAAAAAAAAAAAAAABfilH/X4pR/1+KUf9filH/X4pR/1+KUf9Kc0f/X4pR/ztLPv87Sz7/O0s+/ztLPv87Sz7/O0s+/ztLPv87Sz7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIRMT/wAAAAAAAAAAAAAAAAAAAAAAAAAAX4pR/1+KUf9filH/e59k/1+KUf9filH/SnNH/1+KUf87Sz7/O0s+/ztLPv87Sz7/O0s+/ztLPv87Sz7/O0s+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEpzR/9Kc0f/X4pR/1+KUf9filH/SnNH/0BfQ/9Kc0f/O0s+/ztLPv87Sz7/O0s+/ztLPv87Sz7/O0s+/ztLPv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKc0f/QF9D/0pzR/9filH/X4pR/0pzR/9AX0P/SnNH/0BfQ/87Sz7/QF9D/0BfQ/9AX0P/QF9D/ztLPv9AX0P/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQF9D/0pzR/9filH/X4pR/1+KUf9filH/SnNH/0BfQ/9AX0P/QF9D/0pzR/9Kc0f/SnNH/0pzR/9AX0P/QF9D/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6v/QF9D/0pzR/9filH/X4pR/0pzR/9Kc0f/QF9D/0BfQ/9Kc0f/X4pR/1+KUf9filH/X4pR/0pzR/9AX0P/QF9D/0pzR/9Kc0f/X4pR/1+KUf9Kc0f/QF9D/5aVj/+rq6v/lpWP/5aVj/+rq6v/lpWP/5aVj/+rq6v/lpWP/1+KUf9filH/X4pR/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF+KUf9filH/X4pR/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6ur/6urq/9filH/e59k/1+KUf9filH/SnNH/0pzR/9Kc0f/SnNH/0pzR/9filH/X4pR/0pzR/9Kc0f/SnNH/0pzR/9Kc0f/X4pR/1+KUf97n2T/X4pR/6urq/+WlY//q6ur/6urq/+WlY//lpWP/6urq/+WlY//q6ur/5aVj/9filH/QF9D/0pzR/9filH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF+KUf9Kc0f/QF9D/1+KUf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJaVj/+rq6v/X4pR/1+KUf9filH/SnNH/0BfQ/9AX0P/QF9D/0BfQ/9Kc0f/SnNH/0pzR/9Kc0f/QF9D/0BfQ/9AX0P/QF9D/0pzR/9filH/X4pR/1+KUf+rq6v/lpWP/5aVj/+rq6v/q6ur/5aVj/+WlY//q6ur/6urq/+rq6v/AAAAAEBfQ/9Kc0f/QF9D/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAX0P/SnNH/0BfQ/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzbmr/q6ur/0pzR/9filH/SnNH/0pzR/9AX0P/SnNH/0BfQ//Z2dD/AAAA/1+KUf9AX0P/AAAA/9nZ0P9AX0P/SnNH/0BfQ/9Kc0f/SnNH/1+KUf9Kc0f/q6ur/6urq/9zbmr/q6ur/6urq/+rq6v/lpWP/6urq/+WlY//q6ur/wAAAABKc0f/X4pR/0pzR/9AX0P/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAX0P/SnNH/1+KUf9Kc0f/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc25q/5aVj/9AX0P/X4pR/1+KUf9Kc0f/QF9D/1+KUf9AX0P/X4pR/1+KUf9Kc0f/QF9D/1+KUf9filH/QF9D/1+KUf9AX0P/SnNH/1+KUf9filH/QF9D/5aVj/+rq6v/c25q/5aVj/+WlY//q6ur/3Nuav+rq6v/lpWP/5aVj/8AAAAAAAAAAEpzR/9AX0P/QF9D/0pzR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKc0f/QF9D/0BfQ/9Kc0f/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJSUv+rq6v/lpWP/1+KUf9Kc0f/X4pR/0pzR/9filH/X4pR/1+KUf9Kc0f/SnNH/0pzR/9Kc0f/X4pR/1+KUf9filH/SnNH/1+KUf9Kc0f/X4pR/6urq/+WlY//q6ur/1JSUv+WlY//c25q/6urq/9zbmr/lpWP/6urq/9zbmr/AAAAAAAAAAAAAAAASnNH/0BfQ/9AX0P/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQF9D/0BfQ/9Kc0f/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSUlL/lpWP/3Nuav+WlY//QF9D/0pzR/9Kc0f/SnNH/0pzR/9Kc0f/SnNH/wAAAP8AAAD/SnNH/0pzR/9Kc0f/SnNH/0pzR/9Kc0f/QF9D/5aVj/+rq6v/c25q/5aVj/9SUlL/c25q/3Nuav+WlY//UlJS/5aVj/+rq6v/c25q/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUlJS/5aVj/9SUlL/lpWP/1JSUv87Sz7/QF9D/0BfQ/9AX0P/QF9D/0pzR/9Kc0f/SnNH/0pzR/9AX0P/QF9D/0BfQ/9AX0P/O0s+/5aVj/9zbmr/lpWP/3Nuav+WlY//UlJS/3Nuav9SUlL/c25q/1JSUv9zbmr/lpWP/1JSUv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0Y1T/UktM/1JLTP9SS0z/SnNH/0pzR/9AX0P/O0s+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUktM/5eQcv90Y1T/UktM/1JLTP90Y1T/l5By/1JLTP9SS0z/UktM/1JLTP9SS0z/UktM/1JLTP9SS0z/UktM/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqma/5eQcv+XkHL/dGNU/0BfQ/9AX0P/O0s+/0pzR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5By/3RjVP9SS0z/UktM/0pzR/9AX0P/O0s+/ztLPv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJLTP8hExP/IRMT/yETE/8hExP/IRMT/yETE/9SS0z/UktM/1JLTP9SS0z/UktM/1JLTP9SS0z/UktM/1JLTP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqpmv+qqZr/qqma/5eQcv9Kc0f/v7+4/0BfQ/9AX0P/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJeQcv90Y1T/UktM/zsgHP9Kc0f/QF9D/ztLPv87Sz7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSS0z/IRMT/yETE/8hExP/IRMT/yETE/8hExP/UktM/1JLTP9SS0z/UktM/yETE/8hExP/UktM/1JLTP9SS0z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqqZr/qqma/6qpmv+XkHL/QF9D/0BfQ/87Sz7/QF9D/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0Y1T/UktM/1JLTP87IBz/QF9D/0pzR/9AX0P/O0s+/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUktM/yETE/8hExP/IRMT/yETE/8hExP/IRMT/1JLTP9SS0z/UktM/1JLTP87IBz/IRMT/1JLTP9SS0z/UktM/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqma/5eQcv+XkHL/dGNU/0pzR/+/v7j/QF9D/0pzR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACXkHL/c2Rk/3NkZP+XkHL/l5By/3RjVP9SS0z/IRMT/yETE/8hExP/UktM/1JLTP9SS0z/UktM/3RjVP+XkHL/dGNU/1JLTP9SS0z/UktM/1JLTP8hExP/IRMT/zsgHP87IBz/IRMT/yETE/9SS0z/UktM/1JLTP9SS0z/dGNU/3RjVP+qqZr/l5By/3RjVP90Y1T/l5By/6qpmv90Y1T/qqma/7+/uP+/v7j/qqma/6qpmv+XkHL/dGNU/1JLTP9SS0z/UktM/1JLTP9SS0z/UktM/3RjVP+XkHL/qqma/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5By/3NkZP9zZGT/l5By/6qpmv+XkHL/dGNU/yETE/8hExP/IRMT/1JLTP9SS0z/UktM/3RjVP+XkHL/qqma/5eQcv90Y1T/UktM/1JLTP90Y1T/OyAc/1QxKP9UMSj/VDEo/1QxKP87IBz/dGNU/1JLTP9SS0z/dGNU/5eQcv+qqZr/v7+4/6qpmv+XkHL/l5By/6qpmv+/v7j/qqma/7+/uP+/v7j/v7+4/7+/uP+/v7j/qqma/5eQcv9SS0z/UktM/1JLTP9SS0z/UktM/1JLTP+XkHL/qqma/7+/uP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqpmv9zZGT/c2Rk/6qpmv+qqZr/l5By/3RjVP87IBz/IRMT/yETE/9SS0z/UktM/1JLTP+XkHL/qqma/6qpmv+XkHL/dGNU/1JLTP90Y1T/l5By/1QxKP9wTTr/cE06/3BNOv9wTTr/OyAc/5eQcv90Y1T/UktM/3RjVP+XkHL/qqma/6qpmv90Y1T/qqma/6qpmv90Y1T/qqma/6qpmv+qqZr/v7+4/7+/uP+qqZr/qqma/6qpmv+XkHL/dGNU/1JLTP9SS0z/UktM/1JLTP90Y1T/l5By/6qpmv+qqZr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqqZr/c2Rk/7+/uP+qqZr/qqma/6qpmv+XkHL/OyAc/yETE/8hExP/UktM/1JLTP90Y1T/l5By/6qpmv+qqZr/dGNU/1JLTP90Y1T/l5By/6qpmv87IBz/cE06/4xlSf9wTTr/VDEo/zsgHP+qqZr/l5By/3RjVP9SS0z/dGNU/5eQcv+qqZr/dGNU/5eQcv+XkHL/dGNU/6qpmv+XkHL/l5By/6qpmv+qqZr/l5By/5eQcv+XkHL/l5By/3RjVP9SS0z/UktM/1JLTP9SS0z/dGNU/5eQcv+XkHL/l5By/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv7+4/7+/uP+/v7j/v7+4/6qpmv+XkHL/l5By/zsgHP8hExP/IRMT/1JLTP9SS0z/dGNU/5eQcv+XkHL/qqma/1JLTP9SS0z/UktM/3RjVP+XkHL/OyAc/1QxKP9wTTr/jGVJ/3BNOv+qqZr/l5By/3RjVP9SS0z/UktM/1JLTP9SS0z/dGNU/5eQcv+qqZr/qqma/5eQcv90Y1T/UktM/3RjVP+XkHL/l5By/3RjVP90Y1T/UktM/1JLTP9SS0z/UktM/1JLTP9SS0z/UktM/1JLTP9SS0z/UktM/3RjVP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqpmv+/v7j/v7+4/6qpmv+XkHL/dGNU/1JLTP8hExP/IRMT/yETE/9SS0z/UktM/1JLTP9SS0z/dGNU/5eQcv90Y1T/UktM/1JLTP9SS0z/dGNU/6qpmv9UMSj/cE06/3BNOv9UMSj/qqma/3RjVP9SS0z/UktM/1JLTP90Y1T/l5By/6qpmv+qqZr/v7+4/7+/uP+qqZr/qqma/5eQcv+XkHL/qqma/6qpmv+XkHL/l5By/5eQcv+XkHL/dGNU/1JLTP9SS0z/UktM/1JLTP90Y1T/l5By/5eQcv+XkHL/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqqZr/qqma/6qpmv+qqZr/qqma/5eQcv+XkHL/OyAc/yETE/8hExP/UktM/1JLTP90Y1T/l5By/5eQcv+qqZr/l5By/3RjVP9SS0z/dGNU/5eQcv+qqZr/VDEo/3BNOv9wTTr/OyAc/6qpmv+XkHL/dGNU/1JLTP90Y1T/l5By/6qpmv+/v7j/v7+4/7+/uP+/v7j/v7+4/7+/uP+qqZr/qqma/7+/uP+/v7j/qqma/6qpmv+qqZr/l5By/3RjVP9SS0z/UktM/1JLTP9SS0z/dGNU/5eQcv+qqZr/qqma/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5By/6qpmv+qqZr/l5By/6qpmv+qqZr/l5By/zsgHP8hExP/IRMT/1JLTP9SS0z/dGNU/5eQcv+qqZr/qqma/3RjVP90Y1T/UktM/3RjVP+XkHL/qqma/zsgHP9wTTr/VDEo/zsgHP+qqZr/l5By/3RjVP9SS0z/UktM/3RjVP90Y1T/l5By/6qpmv+/v7j/v7+4/6qpmv+XkHL/dGNU/7+/uP+/v7j/v7+4/7+/uP+/v7j/qqma/5eQcv9SS0z/UktM/1JLTP9SS0z/UktM/1JLTP+XkHL/qqma/7+/uP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJeQcv+XkHL/l5By/5eQcv+XkHL/dGNU/1QxKP87IBz/IRMT/yETE/9SS0z/UktM/1JLTP9SS0z/dGNU/5eQcv90Y1T/dGNU/1JLTP90Y1T/dGNU/6qpmv87IBz/VDEo/3BNOv+qqZr/qqma/3RjVP9SS0z/UktM/1JLTP9SS0z/dGNU/5eQcv+qqZr/v7+4/7+/uP+qqZr/l5By/3RjVP+qqZr/v7+4/7+/uP+qqZr/qqma/5eQcv90Y1T/UktM/1JLTP9SS0z/UktM/1JLTP9SS0z/dGNU/5eQcv+qqZr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKc0f/X4pR/1+KUf9Kc0f/SnNH/0BfQ/9AX0P/O0s+/ztLPv87Sz7/O0s+/ztLPv87Sz7/QF9D/0pzR/9Kc0f/dGNU/3RjVP9SS0z/dGNU/3RjVP+XkHL/qqma/3BNOv9UMSj/qqma/5eQcv90Y1T/UktM/1JLTP9SS0z/UktM/1JLTP+XkHL/qqma/6qpmv+qqZr/qqma/5eQcv9SS0z/X4pR/1+KUf9filH/X4pR/1+KUf9Kc0f/SnNH/0BfQ/87Sz7/O0s+/ztLPv87Sz7/QF9D/0pzR/9Kc0f/X4pR/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX4pR/1+KUf97n2T/X4pR/1+KUf9filH/SnNH/ztLPv87Sz7/O0s+/ztLPv87Sz7/O0s+/0pzR/9filH/X4pR/3RjVP90Y1T/UktM/3RjVP9SS0z/l5By/5eQcv9wTTr/OyAc/5eQcv+XkHL/UktM/1JLTP9SS0z/UktM/1JLTP9SS0z/dGNU/5eQcv+XkHL/l5By/5eQcv90Y1T/UktM/0pzR/9filH/SnNH/1+KUf9Kc0f/QF9D/ztLPv9Kc0f/QF9D/ztLPv87Sz7/QF9D/0pzR/87Sz7/QF9D/0pzR/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF+KUf9filH/X4pR/0pzR/+/v7j/QF9D/7+/uP87Sz7/O0s+/ztLPv87Sz7/O0s+/ztLPv9AX0P/QF9D/0pzR/90Y1T/dGNU/1JLTP90Y1T/UktM/1JLTP90Y1T/VDEo/zsgHP90Y1T/UktM/1JLTP9SS0z/UktM/1JLTP9SS0z/UktM/1JLTP9SS0z/dGNU/3RjVP9SS0z/UktM/1JLTP9AX0P/SnNH/0BfQ/9Kc0f/SnNH/0pzR/9AX0P/SnNH/0BfQ/87Sz7/O0s+/0BfQ/9Kc0f/QF9D/0pzR/9Kc0f/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
                    //	"SkinId": "Standard_Custom",
                    //	"UIProfile": 0
                    //}

                    try
                    {
                        _playerInfo.ClientId         = payload.ClientRandomId;
                        _playerInfo.CurrentInputMode = payload.CurrentInputMode;
                        _playerInfo.DefaultInputMode = payload.DefaultInputMode;
                        _playerInfo.DeviceModel      = payload.DeviceModel;
                        _playerInfo.DeviceOS         = payload.DeviceOS;
                        _playerInfo.GameVersion      = payload.GameVersion;
                        _playerInfo.GuiScale         = payload.GuiScale;
                        _playerInfo.LanguageCode     = payload.LanguageCode;
                        _playerInfo.ServerAddress    = payload.ServerAddress;
                        _playerInfo.UIProfile        = payload.UIProfile;

                        _playerInfo.Skin = new Skin()
                        {
                            SkinType     = payload.SkinId,
                            Texture      = Convert.FromBase64String((string)payload.SkinData),
                            GeometryType = (string)payload.SkinGeometryName,
                            GeometryData = Encoding.ASCII.GetString(Convert.FromBase64String((string)payload.SkinGeometryData))
                        };
                    }
                    catch (Exception e)
                    {
                        Log.Error("Skin info", e);
                    }
                }

                {
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug("Input JSON string: " + certificateChain);
                    }

                    dynamic json = JObject.Parse(certificateChain);

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"JSON:\n{json}");
                    }

                    string validationKey     = null;
                    JArray chain             = json.chain;
                    var    chainArray        = chain.ToArray();
                    string identityPublicKey = null;
                    foreach (dynamic o in chainArray)
                    {
                        IDictionary <string, dynamic> headers = JWT.Headers(o.ToString());

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug("Raw chain element:\n" + o.ToString());
                            Log.Debug($"JWT Header: {string.Join(";", headers)}");

                            dynamic jsonPayload = JObject.Parse(JWT.Payload(o.ToString()));
                            Log.Debug($"JWT Payload:\n{jsonPayload}");
                        }

                        // x5u cert (string): MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V
                        if (headers.ContainsKey("x5u"))
                        {
                            string certString = headers["x5u"];
                            if (identityPublicKey == null && CertificateData.MojangRootKey.Equals(certString, StringComparison.InvariantCultureIgnoreCase))
                            {
                                Log.Debug("Key is ok, and got Mojang root");
                            }
                            else if (identityPublicKey == null)
                            {
                                if (chainArray.Length > 1)
                                {
                                    Log.Debug("Got client cert (client root)");
                                    continue;
                                }
                                else if (chainArray.Length == 1)
                                {
                                    Log.Debug("Selfsigned chain");
                                }
                            }
                            else if (identityPublicKey.Equals(certString))
                            {
                                Log.Debug("Derived Key is ok");
                            }

                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug($"x5u cert (string): {certString}");
                                ECDiffieHellmanPublicKey publicKey = CryptoUtils.CreateEcDiffieHellmanPublicKey(certString);
                                Log.Debug($"Cert:\n{publicKey.ToXmlString()}");
                            }

                            // Validate
                            var             newKey = CryptoUtils.ImportECDsaCngKeyFromString(certString);
                            CertificateData data   = JWT.Decode <CertificateData>(o.ToString(), newKey);
                            if (data != null)
                            {
                                identityPublicKey = data.IdentityPublicKey;

                                if (Log.IsDebugEnabled)
                                {
                                    Log.Debug("Decoded token success");
                                }

                                if (CertificateData.MojangRootKey.Equals(certString, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    Log.Debug("Got Mojang key. Is valid = " + data.CertificateAuthority);
                                    validationKey = data.IdentityPublicKey;
                                }
                                else if (validationKey != null && validationKey.Equals(certString, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    _playerInfo.CertificateData = data;
                                }
                                else
                                {
                                    if (data.ExtraData == null)
                                    {
                                        continue;
                                    }

                                    // Self signed, make sure they don't fake XUID
                                    if (data.ExtraData.Xuid != null)
                                    {
                                        Log.Warn("Received fake XUID from " + data.ExtraData.DisplayName);
                                        data.ExtraData.Xuid = null;
                                    }

                                    _playerInfo.CertificateData = data;
                                }
                            }
                            else
                            {
                                Log.Error("Not a valid Identity Public Key for decoding");
                            }
                        }
                    }

                    //TODO: Implement disconnect here

                    {
                        _playerInfo.Username = _playerInfo.CertificateData.ExtraData.DisplayName;
                        _session.Username    = _playerInfo.Username;
                        string identity = _playerInfo.CertificateData.ExtraData.Identity;

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug($"Connecting user {_playerInfo.Username} with identity={identity}");
                        }
                        _playerInfo.ClientUuid = new UUID(identity);

                        _session.CryptoContext = new CryptoContext
                        {
                            UseEncryption = Config.GetProperty("UseEncryptionForAll", false) || (Config.GetProperty("UseEncryption", true) && !string.IsNullOrWhiteSpace(_playerInfo.CertificateData.ExtraData.Xuid)),
                        };

                        if (_session.CryptoContext.UseEncryption)
                        {
                            ECDiffieHellmanPublicKey publicKey = CryptoUtils.CreateEcDiffieHellmanPublicKey(_playerInfo.CertificateData.IdentityPublicKey);
                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug($"Cert:\n{publicKey.ToXmlString()}");
                            }

                            // Create shared shared secret
                            ECDiffieHellmanCng ecKey = new ECDiffieHellmanCng(384);
                            ecKey.HashAlgorithm         = CngAlgorithm.Sha256;
                            ecKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                            ecKey.SecretPrepend         = Encoding.UTF8.GetBytes("RANDOM SECRET");                     // Server token

                            byte[] secret = ecKey.DeriveKeyMaterial(publicKey);

                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug($"SECRET KEY (b64):\n{Convert.ToBase64String(secret)}");
                            }

                            {
                                RijndaelManaged rijAlg = new RijndaelManaged
                                {
                                    BlockSize    = 128,
                                    Padding      = PaddingMode.None,
                                    Mode         = CipherMode.CFB,
                                    FeedbackSize = 8,
                                    Key          = secret,
                                    IV           = secret.Take(16).ToArray(),
                                };

                                // Create a decrytor to perform the stream transform.
                                ICryptoTransform decryptor      = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
                                MemoryStream     inputStream    = new MemoryStream();
                                CryptoStream     cryptoStreamIn = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read);

                                ICryptoTransform encryptor       = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
                                MemoryStream     outputStream    = new MemoryStream();
                                CryptoStream     cryptoStreamOut = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write);

                                _session.CryptoContext.Algorithm       = rijAlg;
                                _session.CryptoContext.Decryptor       = decryptor;
                                _session.CryptoContext.Encryptor       = encryptor;
                                _session.CryptoContext.InputStream     = inputStream;
                                _session.CryptoContext.OutputStream    = outputStream;
                                _session.CryptoContext.CryptoStreamIn  = cryptoStreamIn;
                                _session.CryptoContext.CryptoStreamOut = cryptoStreamOut;
                            }

                            var response = McpeServerToClientHandshake.CreateObject();
                            response.NoBatch    = true;
                            response.ForceClear = true;

                            string b64Key = Convert.ToBase64String(ecKey.PublicKey.GetDerEncoded());

                            var j = CngKey.Create(CngAlgorithm.ECDiffieHellmanP384, null, new CngKeyCreationParameters()
                            {
                                ExportPolicy = CngExportPolicies.AllowPlaintextExport, KeyUsage = CngKeyUsages.AllUsages
                            });
                            var jwt = JWT.Encode(new object[] {
                                new [] { "salt", "sNUMIRcN2BSNRw93P5vGpg==" }
                            }, j, JwsAlgorithm.ES384, new Dictionary <string, object> {
                                { "x5u", b64Key }
                            });
                            response.token = jwt;

                            _session.SendPackage(response);

                            if (Log.IsDebugEnabled)
                            {
                                Log.Warn($"Encryption enabled for {_session.Username}");
                            }
                        }
                    }
                }

                if (!_session.CryptoContext.UseEncryption)
                {
                    _session.MessageHandler.HandleMcpeClientToServerHandshake(null);
                }
            }
            catch (Exception e)
            {
                Log.Error("Decrypt", e);
            }
        }
Exemple #33
0
        internal void HandlePackage(Package message, PlayerNetworkSession playerSession)
        {
            //SignalTick();

            try
            {
                if (message == null)
                {
                    return;
                }

                if (typeof(UnknownPackage) == message.GetType())
                {
                    UnknownPackage packet = (UnknownPackage)message;
                    if (Log.IsDebugEnabled)
                    {
                        Log.Warn($"Received unknown package 0x{message.Id:X2}\n{Package.HexDump(packet.Message)}");
                    }

                    message.PutPool();
                    return;
                }

                if (typeof(McpeWrapper) == message.GetType())
                {
                    McpeWrapper batch    = (McpeWrapper)message;
                    var         messages = new List <Package>();

                    // Get bytes
                    byte[] payload = batch.payload;
                    if (playerSession.CryptoContext != null && playerSession.CryptoContext.UseEncryption)
                    {
                        throw new Exception("No crypto enabled");
                    }

                    // Decompress bytes

                    MemoryStream stream = new MemoryStream(payload);
                    if (stream.ReadByte() != 0x78)
                    {
                        throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
                    }
                    stream.ReadByte();
                    using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
                    {
                        // Get actual package out of bytes
                        using (MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream())
                        {
                            defStream2.CopyTo(destination);
                            destination.Position = 0;
                            NbtBinaryReader reader = new NbtBinaryReader(destination, true);

                            while (destination.Position < destination.Length)
                            {
                                //int len = reader.ReadInt32();
                                int    len            = BatchUtils.ReadLength(destination);
                                byte[] internalBuffer = reader.ReadBytes(len);

                                //if (Log.IsDebugEnabled)
                                //	Log.Debug($"0x{internalBuffer[0]:x2}\n{Package.HexDump(internalBuffer)}");

                                messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer, "mcpe") ??
                                             new UnknownPackage(internalBuffer[0], internalBuffer));
                            }

                            if (destination.Length > destination.Position)
                            {
                                throw new Exception("Have more data");
                            }
                        }
                    }
                    foreach (var msg in messages)
                    {
                        // Temp fix for performance, take 1.
                        var interact = msg as McpeInteract;
                        if (interact?.actionId == 4 && interact.targetRuntimeEntityId == 0)
                        {
                            continue;
                        }

                        msg.DatagramSequenceNumber = batch.DatagramSequenceNumber;
                        msg.Reliability            = batch.Reliability;
                        msg.ReliableMessageNumber  = batch.ReliableMessageNumber;
                        msg.OrderingChannel        = batch.OrderingChannel;
                        msg.OrderingIndex          = batch.OrderingIndex;
                        HandlePackage(msg, playerSession);
                    }

                    message.PutPool();
                    return;
                }

                MiNetServer.TraceReceive(message);

                if (CryptoContext != null && CryptoContext.UseEncryption)
                {
                    MiNetServer.FastThreadPool.QueueUserWorkItem(delegate()
                    {
                        HandlePackage(MessageHandler, message as Package);
                        message.PutPool();
                    });
                }
                else
                {
                    HandlePackage(MessageHandler, message);
                    message.PutPool();
                }
            }
            catch (Exception e)
            {
                Log.Error("Package handling", e);
                throw;
            }
        }
Exemple #34
0
 internal abstract void SkipTag([NotNull] NbtBinaryReader readStream);
Exemple #35
0
        void LoadFromStreamInternal(Stream stream, TagSelector tagSelector)
        {
            // Make sure the first byte in this file is the tag for a TAG_Compound
            int firstByte = stream.ReadByte();
            if (firstByte < 0)
            {
                throw new EndOfStreamException();
            }
            if (firstByte != (int)NbtTagType.Compound)
            {
                throw new NbtFormatException("Given NBT stream does not start with a TAG_Compound");
            }
            var reader = new NbtBinaryReader(stream, BigEndian)
            {
                Selector = tagSelector
            };

            var rootCompound = new NbtCompound(reader.ReadString());
            rootCompound.ReadTag(reader);
            RootTag = rootCompound;
        }
Exemple #36
0
        public void LabTest()
        {
            // x = 8, z = 9
            string test  = "78daedcdc109c0200004c1233e125bb32f1b4a836a170acec0bef74b52576f294f36f2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f73fe10f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002718974bff9ba43b9b1d578f30";
            string test2 = "789ced5dc9721cc711ed8e09c5486341185877872f085c110179df480220099120294ba47ce4cd115ee99dd64aefa6f7332fd09d3cf80374d00f38829f40ff8088b32f7067cfd44cf774d792f5b23bd14065c470d033fdea655657d6cbaa6e80af6459f6bf939393f1789c57acf8340fb6a3a3a39733d0e6fc930991133d833f17e1cfc7444f0ecc3ee93ffe71959f15be007f3eeffff202f0f865fabf320099f422fc4533c6017ef862e33f8a5f26fe053f9b5ee8fa03e10b8f3fae29f34b8f3f1dfe687ac9f94f317e881f76405dfff3790130e3ee9f7fbcd0bfd907e1f452f3ef78c63fc9caf8fbe65fc43fe130cfe9cfc4fc5b51400dfee8f2435d7fb5f9e5eb2f6ef8eaf3ff19e08fa63f23f143f59f80fee7d50a28eb5f7fabf31f73052837fee6facfe0968bdf6c40b0f985d6bf950d0085f8e76d45d0abafbf64f54fe9fa2ff29ff835f47fd15a04bd74fdc1e3971a7fb1035078fe55e257d75f845f447f117ed401b3fe9e5ba6a0ff739b1075fffbdfcb05302bf64ef879f4a2fb5f31fa2fa93f547ff1e985f557833f371ea88dbf65fc4af5472cbfdcfdb799a95cff61eb9f363faebfd8febf84feeaf2afeefff3f8a5f59f1bff19e05f14006c7ed1f9577dfd3d61872fbbfe52ebff45fcbafaa3a5bfa635edfa8b6fa760ff577bfd2f7dffb97f7e75fd8da69ff1830ee8afffb5d75faef9d7ed91ecfaa3853f73778974fccdf07be07726602ffcb9895f5d7f99fc67abfee01bf17f1ee5cf21fd3d03fa87e93fbefe8db7230101c4f517f300ad3f9e3c295e474f80f8eb1e54e680f27b0fbfe8fcb7d2bc8f5e7cfdc976a0077e9703d2fad720f0f00b3fffd5b45ee3b738d039bfcb016d7e8f75b1fe9d4e19f4eaf587bafe4becff02fb1ff8fa934fbf182122facb0fbec63fd7df680146fbdff0c73ae0609f9de07640f6f9eb167e4f0708d4ffc65aeb8feee3cfedeb3faf0392f3efc4a2ffddf32ff63fb8fc92cf1fb65b0ffc3efdefbaff1bebdfaafebae93be167e8bfc40540f7bf859fbfeadd01b0fe13d87f666f40b4e92f107f04ffb4c11fafbf31f5471b7fa40b8eeb3f3bc1e549b7f35f4ffcd6eb9f791d90dc7f6dd15f1fbfe8fd476dfd8fe0efe3fe431ffa6b77a097f8eb365dd1ffbefbbfaeffbefd8fe1afbfa3d9651c80e347f7df65f6bf91f5377fffa15d7fa3f945ea8f2771559067f2e9a1fe57e6470a90b3a0bfb983bf870d7867fc9e0e10baff99c7f24bdc80aed47f2d0499d38191ccf347e6fed3ec6dda2800acfc42cf3fadee3f04172002dbbf3efd73d18bdd7f8d3611fd2bda595f8fa5175aff0af047eb9fbdff7d5b510dfe080f5c97dfc6df76ff61c67f741411bf53ff3c1d2052ffbb1cf0f0775cff7b1c90d43f1b7fc70b2070ff5beef75f22f557ecf9db56fe00fdc3ef7f2af393030715feeaac9305f0c3cf5fadd43f3c7e587f97e38fdbfd65fdb59c7f63e31f3bea3ffffe4787fbbf5e13d1df72fbb5b500f1de0912d25f5b0f4cf9fa7fc4f6c0a9ffecf84b63f263f5a7e6fe9b8cfee93e00a4fefb1f1e077cf58fc4f33ff3fdff567a3277fca8fe78eb0fab0372fc07083fbafe1dfbf4bf537e7ffd67e31fc9ac3ffdfc96f04775fd8fd5dfdcc36f61cf57eb8fb85d007ffd69e7175dff36f923f43f427f4d6366fe595b83f8b91eacaeffd6d6960ef8cca2ffac6180fcfd2919fdd3d65fdd07803cfcdefa5f60fde5e02f4ff13980ea9ff71650d7fa375f8069f1cf1a73ecffdb1c381270a0f2fc85167ff5fecf68340aeeffbafec7df7fa5b60e2625ffa895bf9dbec11fbdff3cce677fffab3d7e0b7b1b7f94fe9af27ba6bf35fa7cddc5dfa63f6c0766fcebeb9386fe97f2cbe58fd1dfbc1a7fbe22bf7c7ebefe56f9fdfabf2c4bacfc8c2d0044fe2af79f587dbe127f34bdd0fd2ff70d0037bddcfac342ef73406cffd1caef70416efe75f33bf4e714f147afff7c8fe074cb5f63afcb0f8f3ffefeeb41b9ff50fcdbaebfaefa4b40ff2afa3b5a71c049dfa2bfb1fa67fefe675bfc16f676fe88f56f957fb5fec85f7238d0ca1fa3bfe38afe33f865f437afe96f117f4d7e1bfcebeb01facb7060b5fe28f86b0e34e20fe167dc0370de7ff7589d9fd1e92df1b75bd608dfce1f39ff7be49fc11f3bff47dfff179a7ffdfadfe5fcefed7fbb030dfe98fd4fe7affff4c01f547f04f203ebbf7ca6c298fe47de7f2d1b2bf71f2cfa1fcc1f7fff3542ffdbe75fa603e3e5ffbfd1a2ffa43f36769bfef23c30f3bf9cfe73d7bfd5fe67f10be9ef32fe207e71fd5dad3f6a2ef4c06fedde9cb7feece2f91337bf8cfec5c72f34ff47ff0a840cbf2f7ebb07c2fae3e0ef52ff42e20fe58f58ff39cbef1ef89d05681ffcb5df7f85f5ff88fdfc53ee5affe6ae2d4011fd5dfeff1badfc0bf2e9b4b1312ca3bf35fe95fdff4afd315ddd1997dd7f6eeeff1bfe08fde7e96f3eef80f24da4fe88d0ff257fad0088e567ff1e40bb6d6c60f8298847f9b5fdd78effbcfbaf3d7ef4f1b9ffa44ef931fc791fbf43c76b8f9f84d7cd7fedf13374fea1e3b5fb4f3fff503c9abf9803faf1ebe2cffbf83beff10f3f7fcf77fe6beb9f365ebbff878f47f3573dff2107f4fb3fe1111bfefc31f8fc831ad8001bf8efa7d9e7a6103f00ce86af7fdafc91f8db5278fdf8d5f317d4cf5ef27707c45b4d3b7f078a17cbbf38fcaddb2fcc7f8af31fc1eface0b9e953c7b3b367bb4c85cafc85e52f8a47f32fe53f8657d27f9dfcdd7eb581e7f19bb18ee0b757f09cf4294ede46f2bf89e7e5ef34cf76eaf3074fbe8babb5534f455efe15f8ed51047e7b6764f9668e8f9e02b4f3571fafb2feace81703bf6d82ad8d7f0ebe25ff99f9d7c4332230644b3c2b7fc8d91d4a8525fe191f1fcd3fa5584bfcc6e2fab1f26fc1bfec7383773730cfff0d9a7f46edf84f03835831edfcc1f1baf74f58fc3bcd328e953e3baf363ee2e117e7c6e9df4633ffb9f9b38ae7e46f891fd5eb0f36ff8afe73f2b7ac352cf91fd2c0023f6dc1bbf37767e9bf2dff5f8c4a24edfc13c85fd5f51f2b7fdaf31fc6070700e2dbc60a33ff1a0d30f3df860fcddf62fea87f1699bf0b3f38fa3bc38f2cf81703f00bfd6fc347e6bf6efef69a7fedfcf0fd9bbef2cf860f0e00c56f34f1bcfcb7ce1f81f96bc787e56ff3b305fe153f7ed15191f95be2b7b35ad270f2b764ddb1f2e7cffc21348cb57eea008fee5f0ecaff96fc3b25f8b0261cf8a006c0fc6b338efe965973cf86f7e6ef2c6bef66d6fc0bc2df8ac65754df92ff117dd8d3fd8baef1d14df48adf6eeee2f69a7f5de223f79f58fa49ffd8f3372c7fee46e397f91b577fcff017ec785ffe4e3bc87f21fd1b46fe39f0b10d88e143ae9d63fe08c2bbf217e50fc9bf96cf58f9333b635a3d31423fa7f42717daf0cf02f11b597bfdeecbbf0a1ec9dfda32a6868f9a834f3c96f0099ff0a7177f3c70ff133ee1133e1e9ff23fe1137eb878347f7d0e9cf6f8133ee1878cd7cedf94ff099ff0f178347fd5f3dfe300489ff009df297ef0f9e769c08f77371080777601187ec2277ca778f5fc05f5d3e74100ded94008de1502e47cc227bcc7069fbf78fe43faeb6b2004efeac47864c227fc39c87fbc7e87f5db154310ded100e2fb79c06baf3fd5f307c57b22f0e371fd44f1b8fec6e79faf8140bcb50f6271a1f8733ffe51bc7afd8ae2f1fc75b9108407ea5f5f0861783c7f6d0d84e26d0d443b1ecaaf8d1f7cfea078547f61fd565dbffa1a08c40f367f7d0d7861d69eeb099ff20fc4c3fbcf285e75fdea6b20101f5d3ffb3c08c6c7e6af278478cfc3f9513cac1f281e1dbff0f8d7c60f3fff06abbf4b43f1ad0ec43333f0eae31f1dbff0f8d7c6a3f9a75fffa2784b03e1f801e72f8cb7747e303ee50f8887f54f1b8feb278a3fcff96b0f60fed5dd7d4e432b7ead6793fb77e2f185138f1f7e17c27ffcc8fff761ac767c927df4701c8f2fec5ff72178f608c43f7e08c13f79fc1284ff37d2fdc94e81dd03f2375bffe4f103207f8f4f9e82f9fbfc3f0f80fc3d3e598f07cbd84718fce9c713553c3a7f648f307832d410fda7f183cc1f94ff083be53f82cfd0fc6715615d18187f81ff0c84c7ae1fcd1f183e196ab75e43d0cfd7eebee03fcb6a70fe3e5fc3f068fe3fc5f019e8bf40feebe2b397417c32d02ed8fe07b12083c72f863f46f110bab0e7285eb7fff0fc07f99369dbf66711b4faf845f1181c36f5f853fe9e7783fe9b9dc1eb1f064f962c1960caf3c731cc0fe293254b166d68fe6ae393254b166fdaf9ab8e479f5f507ffe2159b2e19a7afe6be3c1f9431b9f2c1962f0f8d5cedf84d7c5a7f9eb7cdbc0f5131dff2709af8a4f960c3174fec0c73ff8fc278c87e0eaf864c9104bf90fc1d5f1c9922186d7ffdaf9ab9bff9aebb70b4bbb78e9caebd7ab8797ae5e3bac1eef1e5cbfb13cbeb4bbf7fae18dead77bd70e6f568ef7f6afdda81cefeeed5fbf71ab02dfbf7cfd66e5786ffff2e1e2f8e2c5fd2b07d76ebef1e6fce812f97678ebdb6f19aeddabd76fdc7ce3addbe670efa000bf79fb4e79f6dee52b570f0bf0ed3b6f97715cbe5ab6551cbe4d4ded5e3928da2a0fbfb3f9c75f5e285f7ff8c5b7367ff393af6dbeffc32f6d3eb8f7d5cd77bfff85cdf77ef0c5f2b3dffdec1be5f70f7fbd5b9efbd777f737ff7cffd2e69f7e75b13c36e77cf8e3af2cdee9f5c18fbe5cbe1b2c61e8e72a1f7d46c7bffde9d7cbf3e945bc744cdf932ff4fafdcfbfb938d7bce87b6a97380943af77bef75af939f94f6dd177f432fed2cfd577f283da270c9d6fb0f419f94efd41be5431745cf8b365e2228c899770e483698bdec95783233fe855e04abcf98c7888975ef4b3e1357dfa9777f6ca77ea076a6fde46796cda212e3a3631d3e7744ce7d1cf7f7bef72f9fac70757cb776a93aea56983de4dcce61ad2e7868bcefffbfb57ca9f291e3aa677131b9d6fae17e1e8736ad38c13c29a971947c607331e8cdf669cd08bce31e7198c39e79f1f1e2cf0c617e32bf94ded55fbdff48de977c2527f10c68c6bc29a18cd98a7cfcd982ce2dca297e91b83317d427d6bda32d7cbf46fd1c656c1bf55f4f196191b2646931f86db5c4bea4f3a97ae0b8d71e22ec618f9b0e0a88eadf978d82adad8227fcd18a7b6e6e3abc417afff0309a69f37";
            string test3 = "7801EDDC310D00000803B02508C0BF5B828A3DAD904E920900000000000000000000000000000000000000000000000000000000000000F016000000000000000000000000000000A86BFF03000000000000000000000000000000000000000000000000000000000000000040CF01072DC034";

            //$ordered = zlib_encode(
            //int chunkX) .
            //int chunkZ) .
            //$orderedIds .
            //$orderedData .
            //$orderedSkyLight .
            //$orderedLight .
            //$this->biomeIds .
            //$biomeColors .
            //$this->tiles


            byte[] val = SoapHexBinary.Parse(test).Value;
            Assert.IsNotNull(val);


            MemoryStream stream = new MemoryStream(val);

            if (stream.ReadByte() != 0x78)
            {
                throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
            }
            stream.ReadByte();
            using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
            {
                NbtBinaryReader defStream = new NbtBinaryReader(defStream2, true);
                ChunkColumn     chunk     = new ChunkColumn();

                chunk.x = IPAddress.NetworkToHostOrder(defStream.ReadInt32());
                chunk.z = IPAddress.NetworkToHostOrder(defStream.ReadInt32());

                int chunkSize = 16 * 16 * 128;
                Assert.AreEqual(chunkSize, defStream.Read(chunk.blocks, 0, chunkSize));
                Assert.AreEqual(chunkSize / 2, defStream.Read(chunk.metadata.Data, 0, chunkSize / 2));
                Assert.AreEqual(chunkSize / 2, defStream.Read(chunk.skylight.Data, 0, chunkSize / 2));
                Assert.AreEqual(chunkSize / 2, defStream.Read(chunk.blocklight.Data, 0, chunkSize / 2));

                Assert.AreEqual(256, defStream.Read(chunk.biomeId, 0, 256));

                byte[] ints = new byte[256 * 4];
                Assert.AreEqual(ints.Length, defStream.Read(ints, 0, ints.Length));
                int j = 0;
                for (int i = 0; i < ints.Length; i = i + 4)
                {
                    chunk.biomeColor[j++] = BitConverter.ToInt32(new[] { ints[i], ints[i + 1], ints[i + 2], ints[i + 3] }, 0);
                }

                MemoryStream uncompressed = new MemoryStream();
                int          b            = -1;
                do
                {
                    b = defStream2.ReadByte();
                    if (b != -1)
                    {
                        uncompressed.WriteByte((byte)b);
                    }
                } while (b != -1);

                Assert.AreEqual(0, uncompressed.Length);
                //Assert.AreEqual(83208, uncompressed.Length);
                Assert.AreEqual(8, chunk.x);
                Assert.AreEqual(9, chunk.z);
                byte[] data = chunk.GetBytes(false);
                Assert.AreEqual(83208, data.Length);                 // Expected uncompressed length
            }
        }
Exemple #37
0
 internal abstract void SkipTag(NbtBinaryReader readStream);
Exemple #38
0
        private void HandleChunk(bool cacheEnabled, uint subChunkCount, byte[] chunkData, int cx, int cz, Action <ChunkColumn> callback)
        {
            if (cacheEnabled)
            {
                Log.Warn($"Unsupported cache enabled!");
            }

            bool gotLight = false;

            try
            {
                using (MemoryStream stream = new MemoryStream(chunkData))
                {
                    NbtBinaryReader defStream = new NbtBinaryReader(stream, true);

                    //int count = defStream.ReadByte();
                    if (subChunkCount < 1)
                    {
                        Log.Warn("Nothing to read");
                        return;
                    }

                    ChunkColumn chunkColumn = new ChunkColumn();
                    chunkColumn.IsDirty = true;
                    chunkColumn.X       = cx;
                    chunkColumn.Z       = cz;

                    for (int s = 0; s < subChunkCount; s++)
                    {
                        var section = chunkColumn.Sections[s] as ChunkSection;

                        int version = defStream.ReadByte();

                        if (version == 1 || version == 8)
                        {
                            int storageSize = defStream.ReadByte();

                            if (section == null)
                            {
                                section = new ChunkSection(chunkColumn, s, true, 2);
                            }

                            for (int storage = 0; storage < storageSize; storage++)
                            {
                                int  paletteAndFlag = defStream.ReadByte();
                                bool isRuntime      = (paletteAndFlag & 1) != 0;
                                int  bitsPerBlock   = paletteAndFlag >> 1;
                                int  blocksPerWord  = (int)Math.Floor(32f / bitsPerBlock);
                                int  wordCount      = (int)Math.Ceiling(4096.0f / blocksPerWord);

                                uint[] words = new uint[wordCount];
                                for (int w = 0; w < wordCount; w++)
                                {
                                    int word = defStream.ReadInt32();
                                    words[w] = SwapBytes((uint)word);
                                }

                                uint[] pallete = new uint[0];

                                if (isRuntime)
                                {
                                    int palleteSize = VarInt.ReadSInt32(stream);
                                    pallete = new uint[palleteSize];

                                    for (int pi = 0; pi < pallete.Length; pi++)
                                    {
                                        var ui = (uint)VarInt.ReadSInt32(stream);
                                        pallete[pi] = ui;
                                    }

                                    if (palleteSize == 0)
                                    {
                                        Log.Warn($"Pallete size is 0");
                                        continue;
                                    }
                                }

                                int position = 0;
                                for (int w = 0; w < wordCount; w++)
                                {
                                    uint word = words[w];
                                    for (int block = 0; block < blocksPerWord; block++)
                                    {
                                        if (position >= 4096)
                                        {
                                            break;                                                   // padding bytes
                                        }
                                        uint state =
                                            (uint)((word >> ((position % blocksPerWord) * bitsPerBlock)) &
                                                   ((1 << bitsPerBlock) - 1));
                                        int x = (position >> 8) & 0xF;
                                        int y = position & 0xF;
                                        int z = (position >> 4) & 0xF;

                                        if (state >= pallete.Length)
                                        {
                                            continue;
                                        }

                                        BlockState translated = GetBlockState(pallete[state]);

                                        if (translated != null)
                                        {
                                            if (translated.Block is Water)
                                            {
                                                string a = "";
                                            }
                                            section.Set(storage, x, y, z, translated);
                                        }

                                        position++;
                                    }

                                    if (position >= 4096)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (section == null)
                            {
                                section = new ChunkSection(chunkColumn, s, true, 1);
                            }

                            #region OldFormat

                            byte[] blockIds = new byte[4096];
                            defStream.Read(blockIds, 0, blockIds.Length);

                            NibbleArray data = new NibbleArray(4096);
                            defStream.Read(data.Data, 0, data.Data.Length);

                            for (int x = 0; x < 16; x++)
                            {
                                for (int z = 0; z < 16; z++)
                                {
                                    for (int y = 0; y < 16; y++)
                                    {
                                        int idx  = (x << 8) + (z << 4) + y;
                                        var id   = blockIds[idx];
                                        var meta = data[idx];

                                        var ruid = BlockFactory.GetBlockStateID(id, meta);

                                        BlockState result = null;

                                        if (!_convertedStates.TryGetValue(
                                                ruid, out result))
                                        {
                                            if (id == 124 || id == 123)
                                            {
                                                result = BlockFactory.GetBlockState("minecraft:redstone_lamp");

                                                if (id == 124)
                                                {
                                                    result = result.WithProperty("lit", "true");
                                                }
                                            }
                                            else if (id > 0 && result == null)
                                            {
                                                var reverseMap =
                                                    MiNET.Worlds.AnvilWorldProvider.Convert.FirstOrDefault(
                                                        map => map.Value.Item1 == id);

                                                if (reverseMap.Value != null)
                                                {
                                                    id = (byte)reverseMap.Key;
                                                }

                                                var res = BlockFactory.GetBlockStateID(id, meta);

                                                if (AnvilWorldProvider.BlockStateMapper.TryGetValue(res, out var res2))
                                                {
                                                    var t = BlockFactory.GetBlockState(res2);
                                                    t = TranslateBlockState(t, id, meta);

                                                    result = t;
                                                }
                                                else
                                                {
                                                    Log.Info($"Did not find anvil statemap: {result.Name}");

                                                    result = TranslateBlockState(
                                                        BlockFactory.GetBlockState(res), id, meta);
                                                }
                                            }

                                            if (result == null)
                                            {
                                                var results = BlockFactory.RuntimeIdTable.Where(xx => xx.Id == id)
                                                              .ToArray();

                                                if (results.Length > 0)
                                                {
                                                    var first = results.FirstOrDefault(xx => xx.Data == meta);

                                                    if (first == default)
                                                    {
                                                        first = results[0];
                                                    }

                                                    result = TranslateBlockState(
                                                        BlockFactory.GetBlockState((uint)first.RuntimeId), id, meta);
                                                }
                                            }

                                            if (result == null)
                                            {
                                                result = new BlockState()
                                                {
                                                    Name  = $"{id}:{meta.ToString()}",
                                                    Model = BlockFactory.UnknownBlockModel,
                                                    Block = new Block(0)
                                                    {
                                                    }
                                                };

                                                Log.Info($"Unknown block: {id}:{meta}");
                                            }

                                            if (result != null)
                                            {
                                                _convertedStates.TryAdd(ruid, result);
                                            }
                                        }

                                        if (result != null)
                                        {
                                            section.Set(x, y, z, result);
                                        }
                                        else
                                        {
                                            Log.Info($"Unknown block: {id}:{meta}");
                                        }
                                    }
                                }
                            }

                            #endregion
                        }

                        if (UseAlexChunks)
                        {
                            //  Log.Info($"Alex chunk!");

                            var rawSky = new API.Utils.NibbleArray(4096);
                            defStream.Read(rawSky.Data, 0, rawSky.Data.Length);

                            var rawBlock = new API.Utils.NibbleArray(4096);
                            defStream.Read(rawBlock.Data, 0, rawBlock.Data.Length);

                            for (int x = 0; x < 16; x++)
                            {
                                for (int y = 0; y < 16; y++)
                                {
                                    for (int z = 0; z < 16; z++)
                                    {
                                        var peIndex = (x * 256) + (z * 16) + y;
                                        var sky     = rawSky[peIndex];
                                        var block   = rawBlock[peIndex];

                                        var idx = y << 8 | z << 4 | x;

                                        section.SkyLight[idx]   = sky;
                                        section.BlockLight[idx] = block;
                                    }
                                }
                            }

                            gotLight = true;
                        }

                        section.RemoveInvalidBlocks();
                        section.IsDirty = true;

                        //Make sure the section is saved.
                        chunkColumn.Sections[s] = section;
                    }


                    /* byte[] ba = new byte[512];
                     * if (defStream.Read(ba, 0, 256 * 2) != 256 * 2) Log.Error($"Out of data height");
                     *
                     * Buffer.BlockCopy(ba, 0, chunkColumn.Height, 0, 512);*/

                    int[] biomeIds = new int[256];
                    for (int i = 0; i < biomeIds.Length; i++)
                    {
                        biomeIds[i] = defStream.ReadByte();
                    }

                    chunkColumn.BiomeId = biomeIds;

                    if (stream.Position >= stream.Length - 1)
                    {
                        callback?.Invoke(chunkColumn);
                        return;
                    }

                    int borderBlock = VarInt.ReadSInt32(stream);
                    if (borderBlock > 0)
                    {
                        byte[] buf = new byte[borderBlock];
                        int    len = defStream.Read(buf, 0, borderBlock);
                    }


                    if (stream.Position < stream.Length - 1)
                    {
                        int loop = 0;
                        while (stream.Position < stream.Length - 1)
                        {
                            try
                            {
                                NbtFile file = new NbtFile()
                                {
                                    BigEndian = false,
                                    UseVarInt = true
                                };

                                file.LoadFromStream(stream, NbtCompression.None);

                                if (file.RootTag.Name == "alex")
                                {
                                    NbtCompound alexCompound = (NbtCompound)file.RootTag;

                                    for (int ci = 0; ci < subChunkCount; ci++)
                                    {
                                        var section = (ChunkSection)chunkColumn.Sections[ci];

                                        var rawSky = new API.Utils.NibbleArray(4096);
                                        if (alexCompound.TryGet($"skylight-{ci}", out NbtByteArray skyData))
                                        {
                                            rawSky.Data = skyData.Value;
                                        }
                                        //defStream.Read(rawSky.Data, 0, rawSky.Data.Length);

                                        var rawBlock = new API.Utils.NibbleArray(4096);
                                        if (alexCompound.TryGet($"blocklight-{ci}", out NbtByteArray blockData))
                                        {
                                            rawBlock.Data = blockData.Value;
                                        }

                                        for (int x = 0; x < 16; x++)
                                        {
                                            for (int y = 0; y < 16; y++)
                                            {
                                                for (int z = 0; z < 16; z++)
                                                {
                                                    var peIndex = (x * 256) + (z * 16) + y;
                                                    var sky     = rawSky[peIndex];
                                                    var block   = rawBlock[peIndex];

                                                    var idx = y << 8 | z << 4 | x;

                                                    section.SkyLight[idx]   = sky;
                                                    section.BlockLight[idx] = block;
                                                }
                                            }
                                        }

                                        chunkColumn.Sections[ci] = section;
                                    }

                                    gotLight = true;
                                }

                                if (stream.Position < stream.Length - 1)
                                {
                                    //   pre = stream.ReadByte();
                                }
                            }
                            catch (Exception ex)
                            {
                                // Log.Warn(ex, $"Reading chunk extra data (Loop={loop})");
                            }

                            loop++;
                        }
                    }

                    if (stream.Position < stream.Length - 1)
                    {
                        Log.Warn(
                            $"Still have data to read\n{Packet.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");
                    }

                    if (gotLight)
                    {
                        chunkColumn.SkyLightDirty   = false;
                        chunkColumn.BlockLightDirty = false;
                    }

                    chunkColumn.CalculateHeight(!gotLight && ClientSideLighting);

                    //Done processing this chunk, send to world
                    callback?.Invoke(chunkColumn);
                }
            }
            catch (Exception ex)
            {
                Log.Error($"Exception in chunk loading: {ex.ToString()}");
            }
            finally
            {
            }
        }
Exemple #39
0
 internal override void SkipTag(NbtBinaryReader readStream)
 {
     int length = readStream.ReadInt32();
     if (length < 0)
     {
         throw new NbtFormatException("Negative length given in TAG_Byte_Array");
     }
     readStream.Skip(length);
 }
Exemple #40
0
 internal override void SkipTag(NbtBinaryReader readStream)
 {
     readStream.ReadByte();
 }
Exemple #41
0
 internal abstract bool ReadTag(NbtBinaryReader readStream);
        protected void DecodeCert(McpeLogin message)
        {
            _playerInfo = new PlayerInfo();

            // Get bytes
            byte[] buffer = message.payload;

            //Log.Debug($"Unknown byte in login packet is: {message.unknown}");

            if (message.payload.Length != buffer.Length)
            {
                Log.Debug($"Wrong lenght {message.payload.Length} != {message.payload.Length}");
                throw new Exception($"Wrong lenght {message.payload.Length} != {message.payload.Length}");
            }
            // Decompress bytes

            Log.Debug("Lenght: " + message.payload.Length + ", Message: " + Convert.ToBase64String(buffer));

            //MemoryStream stream = new MemoryStream(buffer);
            //if (stream.ReadByte() != 0x78)
            //{
            //	throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
            //}
            //stream.ReadByte();

            string certificateChain;
            string skinData;

            //using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
            {
                // Get actual package out of bytes
                //using (MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream())
                {
                    //defStream2.CopyTo(destination);

                    var destination = new MemoryStream(buffer);
                    destination.Position = 0;
                    NbtBinaryReader reader = new NbtBinaryReader(destination, false);

                    try
                    {
                        var countCertData = reader.ReadInt32();
                        Log.Debug("Count cert: " + countCertData);
                        certificateChain = Encoding.UTF8.GetString(reader.ReadBytes(countCertData));
                        Log.Debug("Decompressed certificateChain " + certificateChain);

                        var countSkinData = reader.ReadInt32();
                        Log.Debug("Count skin: " + countSkinData);
                        skinData = Encoding.UTF8.GetString(reader.ReadBytes(countSkinData));
                        Log.Debug("Decompressed skinData" + skinData);
                    }
                    catch (Exception e)
                    {
                        Log.Error("Parsing login", e);
                        return;
                    }
                }
            }


            try
            {
                {
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug("Input SKIN string: " + skinData);
                    }

                    IDictionary <string, dynamic> headers = JWT.Headers(skinData);
                    dynamic payload = JObject.Parse(JWT.Payload(skinData));

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Skin JWT Header: {string.Join(";", headers)}");
                    }
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Skin JWT Payload:\n{payload.ToString()}");
                    }

                    // Skin JWT Payload:

                    //{
                    //	"ADRole": 2,
                    //	"ClientRandomId": -1256727416,
                    //	"CurrentInputMode": 2,
                    //	"DefaultInputMode": 2,
                    //	"DeviceModel": "SAMSUNG GT-P5210",
                    //	"DeviceOS": 1,
                    //	"GameVersion": "1.0.3.0",
                    //	"GuiScale": 0,
                    //	"ServerAddress": "192.168.0.3:19132",
                    //	"SkinData": "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Af/3/wH/9/8B//f/Af/3/wAAAP/yrmj/8q5o//KuaP/yrmj/8q5o//KuaP/yrmj/8q5o/wMCAv8B//f/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD//wAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgD/AQEB/wEBAf8BAQH//fn2//359v/9+fb//fn2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQUF/wkICP8JCQn/EhIS//KuaP/yrmj/AAAA/wkJCf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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",
                    //	"SkinId": "Standard_Custom",
                    //	"TenantId": "",
                    //	"UIProfile": 1
                    //}

                    try
                    {
                        _playerInfo.ADRole           = payload.ADRole;
                        _playerInfo.ClientId         = payload.ClientRandomId;
                        _playerInfo.CurrentInputMode = payload.CurrentInputMode;
                        _playerInfo.DefaultInputMode = payload.DefaultInputMode;
                        _playerInfo.DeviceModel      = payload.DeviceModel;
                        _playerInfo.DeviceOS         = payload.DeviceOS;
                        _playerInfo.GameVersion      = payload.GameVersion;
                        _playerInfo.GuiScale         = payload.GuiScale;
                        _playerInfo.ServerAddress    = payload.ServerAddress;
                        _playerInfo.UIProfile        = payload.UIProfile;

                        _playerInfo.Skin = new Skin()
                        {
                            SkinType = payload.SkinId,
                            Texture  = Convert.FromBase64String((string)payload.SkinData),
                        };
                    }
                    catch (Exception e)
                    {
                        Log.Error("Skin info", e);
                    }
                }

                {
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug("Input JSON string: " + certificateChain);
                    }

                    dynamic json = JObject.Parse(certificateChain);

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"JSON:\n{json}");
                    }

                    string validationKey = null;
                    foreach (dynamic o in json.chain)
                    {
                        IDictionary <string, dynamic> headers = JWT.Headers(o.ToString());

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug("Raw chain element:\n" + o.ToString());
                            Log.Debug($"JWT Header: {string.Join(";", headers)}");

                            dynamic jsonPayload = JObject.Parse(JWT.Payload(o.ToString()));
                            Log.Debug($"JWT Payload:\n{jsonPayload}");
                        }

                        // x5u cert (string): MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V
                        if (headers.ContainsKey("x5u"))
                        {
                            string certString = headers["x5u"];

                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug($"x5u cert (string): {certString}");
                                ECDiffieHellmanPublicKey publicKey = CryptoUtils.CreateEcDiffieHellmanPublicKey(certString);
                                Log.Debug($"Cert:\n{publicKey.ToXmlString()}");
                            }

                            // Validate
                            CngKey          newKey = CryptoUtils.ImportECDsaCngKeyFromString(certString);
                            CertificateData data   = JWT.Decode <CertificateData>(o.ToString(), newKey);

                            if (data != null)
                            {
                                if (Log.IsDebugEnabled)
                                {
                                    Log.Debug("Decoded token success");
                                }

                                if (CertificateData.MojangRootKey.Equals(certString, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    Log.Debug("Got Mojang key. Is valid = " + data.CertificateAuthority);
                                    validationKey = data.IdentityPublicKey;
                                }
                                else if (validationKey != null && validationKey.Equals(certString, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    _playerInfo.CertificateData = data;
                                }
                                else
                                {
                                    if (data.ExtraData == null)
                                    {
                                        continue;
                                    }

                                    // Self signed, make sure they don't fake XUID
                                    if (data.ExtraData.Xuid != null)
                                    {
                                        Log.Warn("Received fake XUID from " + data.ExtraData.DisplayName);
                                        data.ExtraData.Xuid = null;
                                    }

                                    _playerInfo.CertificateData = data;
                                }
                            }
                            else
                            {
                                Log.Error("Not a valid Identity Public Key for decoding");
                            }
                        }
                    }

                    //TODO: Implement disconnect here

                    {
                        _playerInfo.Username = _playerInfo.CertificateData.ExtraData.DisplayName;
                        _session.Username    = _playerInfo.Username;
                        string identity = _playerInfo.CertificateData.ExtraData.Identity;

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug($"Connecting user {_playerInfo.Username} with identity={identity}");
                        }
                        _playerInfo.ClientUuid = new UUID(identity);

                        _session.CryptoContext = new CryptoContext
                        {
                            UseEncryption = Config.GetProperty("UseEncryptionForAll", false) || (Config.GetProperty("UseEncryption", true) && !string.IsNullOrWhiteSpace(_playerInfo.CertificateData.ExtraData.Xuid)),
                        };

                        if (_session.CryptoContext.UseEncryption)
                        {
                            ECDiffieHellmanPublicKey publicKey = CryptoUtils.CreateEcDiffieHellmanPublicKey(_playerInfo.CertificateData.IdentityPublicKey);
                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug($"Cert:\n{publicKey.ToXmlString()}");
                            }

                            // Create shared shared secret
                            ECDiffieHellmanCng ecKey = new ECDiffieHellmanCng(384);
                            ecKey.HashAlgorithm         = CngAlgorithm.Sha256;
                            ecKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                            ecKey.SecretPrepend         = Encoding.UTF8.GetBytes("RANDOM SECRET");                     // Server token

                            byte[] secret = ecKey.DeriveKeyMaterial(publicKey);

                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug($"SECRET KEY (b64):\n{Convert.ToBase64String(secret)}");
                            }

                            {
                                RijndaelManaged rijAlg = new RijndaelManaged
                                {
                                    BlockSize    = 128,
                                    Padding      = PaddingMode.None,
                                    Mode         = CipherMode.CFB,
                                    FeedbackSize = 8,
                                    Key          = secret,
                                    IV           = secret.Take(16).ToArray(),
                                };

                                // Create a decrytor to perform the stream transform.
                                ICryptoTransform decryptor      = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
                                MemoryStream     inputStream    = new MemoryStream();
                                CryptoStream     cryptoStreamIn = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read);

                                ICryptoTransform encryptor       = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
                                MemoryStream     outputStream    = new MemoryStream();
                                CryptoStream     cryptoStreamOut = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write);

                                _session.CryptoContext.Algorithm       = rijAlg;
                                _session.CryptoContext.Decryptor       = decryptor;
                                _session.CryptoContext.Encryptor       = encryptor;
                                _session.CryptoContext.InputStream     = inputStream;
                                _session.CryptoContext.OutputStream    = outputStream;
                                _session.CryptoContext.CryptoStreamIn  = cryptoStreamIn;
                                _session.CryptoContext.CryptoStreamOut = cryptoStreamOut;
                            }

                            var response = McpeServerToClientHandshake.CreateObject();
                            response.NoBatch         = true;
                            response.ForceClear      = true;
                            response.serverPublicKey = Convert.ToBase64String(ecKey.PublicKey.GetDerEncoded());
                            response.tokenLength     = (short)ecKey.SecretPrepend.Length;
                            response.token           = ecKey.SecretPrepend;

                            _session.SendPackage(response);

                            if (Log.IsDebugEnabled)
                            {
                                Log.Warn($"Encryption enabled for {_session.Username}");
                            }
                        }
                    }
                }

                if (!_session.CryptoContext.UseEncryption)
                {
                    _session.MessageHandler.HandleMcpeClientToServerHandshake(null);
                }
            }
            catch (Exception e)
            {
                Log.Error("Decrypt", e);
            }
        }
Exemple #43
0
        static string GetRootNameInternal(Stream stream, bool bigEndian)
        {
            Debug.Assert(stream != null);
            int firstByte = stream.ReadByte();
            if (firstByte < 0)
            {
                throw new EndOfStreamException();
            }
            else if (firstByte != (int)NbtTagType.Compound)
            {
                throw new NbtFormatException("Given NBT stream does not start with a TAG_Compound");
            }
            var reader = new NbtBinaryReader(stream, bigEndian);

            return reader.ReadString();
        }