Example #1
0
        public override void HandleMcpeStartGame(McpeStartGame message)
        {
            Client.EntityId        = message.runtimeEntityId;
            Client.NetworkEntityId = message.entityIdSelf;
            Client.SpawnPoint      = message.spawn;
            Client.CurrentLocation = new PlayerLocation(Client.SpawnPoint, message.rotation.X, message.rotation.X, message.rotation.Y);

            Client.LevelInfo.LevelName = message.levelId;
            Client.LevelInfo.Version   = 19133;
            Client.LevelInfo.GameType  = message.gamemode;

            _blockPallet = message.blockPallet;

            _internalStates = new HashSet <BlockRecord>(BlockFactory.BlockPallet);

            //ClientUtils.SaveLevel(_level);

            {
                int viewDistance = Config.GetProperty("ViewDistance", 11);

                var packet = McpeRequestChunkRadius.CreateObject();
                Client.ChunkRadius = viewDistance;
                packet.chunkRadius = Client.ChunkRadius;

                Client.SendPacket(packet);
            }
        }
Example #2
0
        private static uint GetHashRuntimeId(BlockPallet bedrockPallet, HashSet <BlockRecord> internalBlockPallet, int runtimeId)
        {
            if (runtimeId < 0 || runtimeId >= bedrockPallet.Count)
            {
                Log.Error($"RuntimeId = {runtimeId}");
            }

            var record = bedrockPallet[runtimeId];

            if (!internalBlockPallet.TryGetValue(record, out BlockRecord internalRecord))
            {
                Log.Error($"Did not find {record.Id}");
                return(0);                // air
            }
            uint hash = (uint)((internalRecord.Id << 4) | (byte)internalRecord.Data);

            return(hash);
        }
Example #3
0
        public void GenerateClassesForBlocks()
        {
            BlockPallet pallet = null;

            var assembly = Assembly.GetAssembly(typeof(Block));

            using (var stream = assembly.GetManifestResourceStream(typeof(Block).Namespace + ".blockstates.json"))
                using (var reader = new StreamReader(stream))
                {
                    pallet = BlockPallet.FromJson(reader.ReadToEnd());
                }

            List <(int, string)> blocks = new List <(int, string)>();

            string fileName = Path.GetTempPath() + "MissingBlocks_" + Guid.NewGuid() + ".txt";

            using (FileStream file = File.OpenWrite(fileName))
            {
                Log.Warn($"Writing new blocks to filename:\n{fileName}");

                IndentedTextWriter writer = new IndentedTextWriter(new StreamWriter(file));

                writer.WriteLine($"namespace MiNET.Blocks");
                writer.WriteLine($"{{");
                writer.Indent++;


                foreach (IGrouping <string, BlockRecord> blockstate in pallet.OrderBy(r => r.Name).ThenBy(r => r.Data).GroupBy(r => r.Name))
                {
                    var enumerator = blockstate.GetEnumerator();
                    enumerator.MoveNext();
                    var value = enumerator.Current;
                    if (value == null)
                    {
                        continue;
                    }
                    Log.Debug($"{value.RuntimeId}, {value.Name}, {value.Data}");
                    int id = BlockFactory.GetBlockIdByName(value.Name.Replace("minecraft:", ""));

                    if (id == 0 && !value.Name.Contains("air"))
                    {
                        string blockName = CodeName(value.Name.Replace("minecraft:", ""), true);

                        blocks.Add((value.Id, blockName));

                        writer.WriteLine($"public class {blockName}: Block");
                        writer.WriteLine($"{{");
                        writer.Indent++;

                        writer.WriteLine($"public {blockName}() : base({value.Id})");
                        writer.WriteLine($"{{");
                        writer.Indent++;

                        writer.WriteLine($"Name = \"{value.Name}\";");

                        do
                        {
                            writer.WriteLine($"// runtime id: {enumerator.Current.RuntimeId} 0x{enumerator.Current.RuntimeId:X}, data: {enumerator.Current.Data}");
                        } while (enumerator.MoveNext());

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

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

                foreach (var block in blocks.OrderBy(tuple => tuple.Item1))
                {
                    writer.WriteLine($"else if (blockId == {block.Item1}) block = new {block.Item2}();");
                }

                writer.Flush();
            }
        }
Example #4
0
        public static ChunkColumn DecodeChunkColumn(int subChunkCount, byte[] buffer, BlockPallet bedrockPallet = null, HashSet <BlockRecord> 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();

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

                        var section = (PaletteChunk)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}, " +
                                      $"bitsPerBlock={bitsPerBlock}, " +
                                      $"noBlocksPerWord={blocksPerWord}, " +
                                      $"wordCount={wordsPerChunk}, " +
                                      $"");

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

                            int paletteCount = VarInt.ReadSInt32(stream);
                            var palette      = new uint[paletteCount];
                            for (int j = 0; j < paletteCount; j++)
                            {
                                palette[j] = GetHashRuntimeId(bedrockPallet, internalBlockPallet, VarInt.ReadSInt32(stream));
                            }

                            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;

                                    uint hash = palette[state];

                                    int bid = (int)(hash >> 4);
                                    if (BlockFactory.GetBlockById(bid).GetType() == typeof(Block))
                                    {
                                        //Log.Error($"No block for bid={bid}");
                                        bid = 0;
                                    }

                                    if (storageIndex == 0)
                                    {
                                        section.SetBlock(x, y, z, bid);
                                        section.SetMetadata(x, y, z, (byte)(hash & 0xf));
                                    }
                                    else
                                    {
                                        section.SetLoggedBlock(x, y, z, bid);
                                        section.SetLoggedMetadata(x, y, z, (byte)(hash & 0xf));
                                    }

                                    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;
                            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: {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);
                }
            }
        }