Пример #1
0
        public bool TryConvertBlockState(BlockStateContainer record, out BlockState result)
        {
            if (_convertedStates.TryGetValue((uint)record.RuntimeId, out var alreadyConverted))
            {
                result = alreadyConverted;
                return(true);
            }

            result = null;

            string searchName = record.Name;

            switch (record.Name)
            {
            case "minecraft:torch":
                if (record.States.Any(x => x.Name.Equals("torch_facing_direction") && x.Value() != "top"))
                {
                    searchName = "minecraft:wall_torch";
                }
                break;

            case "minecraft:unlit_redstone_torch":
            case "minecraft:redstone_torch":
                if (record.States.Any(x => x.Name.Equals("torch_facing_direction") && x.Value() != "top"))
                {
                    searchName = "minecraft:redstone_wall_torch";
                }
                break;

            case "minecraft:flowing_water":
                searchName = "minecraft:water";
                break;

            case "minecraft:wood":
                searchName = GetWoodBlock(record);
                break;

            case "minecraft:tallgrass":
                searchName = "minecraft:tall_grass";
                break;
            }

            string prefix = "";

            foreach (var state in record.States.ToArray())
            {
                switch (state.Name)
                {
                case "stone_type":
                    switch (state.Value())
                    {
                    case "granite":
                    case "diorite":
                    case "andesite":
                        searchName = $"minecraft:{state.Value()}";
                        break;

                    case "granite_smooth":
                    case "diorite_smooth":
                    case "andesite_smooth":
                        var split = state.Value().Split('_');
                        searchName = $"minecraft:polished_{split[0]}";
                        break;
                    }

                    break;

                case "old_log_type":
                {
                    searchName = $"minecraft:{state.Value()}_log";
                }
                break;

                case "old_leaf_type":
                    searchName = $"minecraft:{state.Value()}_leaves";
                    break;

                case "wood_type":
                    switch (record.Name.ToLower())
                    {
                    case "minecraft:fence":
                        searchName = $"minecraft:{state.Value()}_fence";
                        break;

                    case "minecraft:planks":
                        searchName = $"minecraft:{state.Value()}_planks";
                        break;

                    case "minecraft:wooden_slab":
                        searchName = $"minecraft:{state.Value()}_slab";
                        break;
                        //  case "minecraft:wood":
                        //      searchName = $"minecraft:{state.Value}_log";
                        //       break;
                    }

                    break;

                case "sapling_type":
                    //case "old_log_type":
                    // case "old_leaf_type":
                    searchName = $"minecraft:{state.Value()}_sapling";
                    //prefix = "_";
                    break;

                case "flower_type":
                    searchName = $"minecraft:{state.Value()}";
                    break;

                case "double_plant_type":

                    switch (state.Value())
                    {
                    case "grass":
                        searchName = "minecraft:tall_grass";
                        break;

                    case "sunflower":
                        searchName = "minecraft:sunflower";
                        break;

                    case "fern":
                        searchName = "minecraft:large_fern";
                        break;

                    case "rose":
                        searchName = "minecraft:rose_bush";
                        break;

                    case "paeonia":
                        searchName = "minecraft:peony";
                        break;
                    }

                    break;

                case "color":
                    switch (record.Name)
                    {
                    case "minecraft:carpet":
                        searchName = $"minecraft:{state.Value()}_carpet";
                        break;

                    case "minecraft:wool":
                        searchName = $"minecraft:{state.Value()}_wool";
                        break;

                    case "minecraft:stained_glass":
                        searchName = $"minecraft:{state.Value()}_stained_glass";
                        break;

                    case "minecraft:concrete":
                        searchName = $"minecraft:{state.Value()}_concrete";
                        break;

                    case "minecraft:stained_glass_pane":
                        searchName = $"minecraft:{state.Value()}_stained_glass_pane";
                        break;
                    }

                    record.States.Remove(state);
                    break;
                }
            }

            BlockState r;    // = BlockFactory.GetBlockState(record.Name);

            r = BlockFactory.GetBlockState(prefix + searchName);

            if (r == null || r.Name == "Unknown")
            {
                r = BlockFactory.GetBlockState(searchName);
            }

            if (r == null || r.Name == "Unknown")
            {
                var mapResult =
                    BlockFactory.RuntimeIdTable.FirstOrDefault(xx =>
                                                               xx.Name == searchName);

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

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

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

                    if (AnvilWorldProvider.BlockStateMapper.TryGetValue(
                            res,
                            out var res2))
                    {
                        r = BlockFactory.GetBlockState(res2);
                    }
                    else
                    {
                        Log.Info(
                            $"Did not find anvil statemap: {result.Name}");
                        r = BlockFactory.GetBlockState(mapResult.Name);
                    }
                }
            }

            if (r == null || r.Name == "Unknown")
            {
                Log.Warn($"Could not translate block: {record.Name}");
                return(false);
            }

            foreach (var state in record.States)
            {
                switch (state.Name)
                {
                case "direction":
                case "weirdo_direction":
                    if (r.Block is FenceGate)
                    {
                        switch (state.Value())
                        {
                        case "0":
                            r = r.WithProperty(facing, "north");
                            break;

                        case "1":
                            r = r.WithProperty(facing, "west");
                            break;

                        case "2":
                            r = r.WithProperty(facing, "south");
                            break;

                        case "3":
                            r = r.WithProperty(facing, "east");
                            break;
                        }
                    }
                    else
                    {
                        r = FixFacing(r, int.Parse(state.Value()));
                    }

                    break;

                case "upside_down_bit":
                    r = (r).WithProperty("half", state.Value() == "1" ? "top" : "bottom");
                    break;

                case "door_hinge_bit":
                    r = r.WithProperty("hinge", (state.Value() == "0") ? "left" : "right");
                    break;

                case "open_bit":
                    r = r.WithProperty("open", (state.Value() == "1") ? "true" : "false");
                    break;

                case "upper_block_bit":
                    r = r.WithProperty("half", (state.Value() == "1") ? "upper" : "lower");
                    break;

                case "torch_facing_direction":
                    string facingValue = state.Value();
                    switch (facingValue)
                    {
                    case "north":
                        facingValue = "south";
                        break;

                    case "east":
                        facingValue = "west";
                        break;

                    case "south":
                        facingValue = "north";
                        break;

                    case "west":
                        facingValue = "east";
                        break;
                    }
                    r = r.WithProperty("facing", facingValue);
                    break;

                case "liquid_depth":
                    r = r.WithProperty("level", state.Value());
                    break;

                case "height":
                    r = r.WithProperty("layers", state.Value());
                    break;

                case "growth":
                    r = r.WithProperty("age", state.Value());
                    break;

                case "button_pressed_bit":
                    r = r.WithProperty("powered", state.Value() == "1" ? "true" : "false");
                    break;

                case "facing_direction":
                    switch (int.Parse(state.Value()))
                    {
                    case 0:
                    case 4:
                        r = r.WithProperty(facing, "west");
                        break;

                    case 1:
                    case 5:
                        r = r.WithProperty(facing, "east");
                        break;

                    case 6:
                    case 2:
                        r = r.WithProperty(facing, "north");
                        break;

                    case 7:
                    case 3:
                        r = r.WithProperty(facing, "south");
                        break;
                    }
                    break;

                case "head_piece_bit":
                    r = r.WithProperty("part", state.Value() == "1" ? "head" : "foot");
                    break;

                case "pillar_axis":
                    r = r.WithProperty("axis", state.Value());
                    break;

                case "top_slot_bit":
                    r = r.WithProperty("type", state.Value() == "1" ? "top" : "bottom", true);
                    break;

                case "moisturized_amount":
                    r = r.WithProperty("moisture", state.Value());
                    break;

                case "age":
                    r = r.WithProperty("age", state.Value());
                    break;

                default:
                    //	        Log.Info($"Unknown property for {record.Name}: {state.Name} - {state.Value()}");
                    //	r = r.WithProperty(state.Name, state.Value());
                    break;
                }
            }

            if (record.Name.Equals("minecraft:unlit_redstone_torch"))
            {
                r = r.WithProperty("lit", "false");
            }

            result = r;

            return(true);
        }
Пример #2
0
 protected Block(int blockId, byte metadata) : this(BlockFactory.GetBlockStateID(blockId, metadata))
 {
     // LightOpacity = 2;
 }
Пример #3
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
            {
            }
        }
Пример #4
0
        public static Item ToAlexItem(this MiNET.Items.Item item)
        {
            if (item == null)
            {
                return(new ItemAir());
            }

            Item result = null;

            if (ChunkProcessor.Itemstates.TryGetValue(item.Id, out var itemState))
            {
                //item.Id = itemState.Id;
                if (ItemFactory.TryGetItem(itemState.Id, item.Metadata, out result) || ItemFactory.TryGetItem(itemState.Name, out result))
                {
                    //	Log.Info($"{item.Id} = {JsonConvert.SerializeObject(itemState, SerializerSettings)} || {JsonConvert.SerializeObject(result, SerializerSettings)}");
                }
                else
                {
                    //	Log.Info($"{item.Id} = {JsonConvert.SerializeObject(itemState, SerializerSettings)}");
                }
            }

            if (result == null && item.Id < 256)             //Block
            {
                var id         = item.Id;
                var meta       = (byte)item.Metadata;
                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);

                    ItemFactory.TryGetItem(t.Name, out result);
                }
                else
                {
                    var block = BlockFactory.RuntimeIdTable.FirstOrDefault(x => x.Id == item.Id);

                    if (block != null)
                    {
                        ItemFactory.TryGetItem(block.Name, out result);
                    }
                }

                if (result != null)
                {
                    //result.Id = item.Id;
                    //result.Meta = item.Metadata;
                }
            }

            if (result == null)
            {
                ItemFactory.TryGetItem(item.Id, item.Metadata, out result);
                //  Log.Info($"Set inventory slot: {message.slot} Id: {message.item.Id}:{message.item.Metadata} x {message.item.Count} Name: {item.DisplayName} IsPeInv: {inventory.IsPeInventory}");
            }

            if (result != null)
            {
                result.StackID = item.UniqueId;
                result.Meta    = item.Metadata;
                result.Count   = item.Count;
                result.Nbt     = item.ExtraData;
                result.Id      = item.Id;

                return(result);
            }

            return(new ItemAir()
            {
                Count = 0
            });
        }
Пример #5
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();
            }
        }
Пример #6
0
        public override void HandleMcpeUpdateBlock(McpeUpdateBlock message)
        {
            if (message.storage != 0)
            {
                Log.Warn($"UPDATEBLOCK: Unsupported block storage! {message.storage}");
                return;
            }

            if (_blockStateMap.TryGetValue(message.blockRuntimeId, out var bs))
            {
                IBlockState state = null;

                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 = ChunkProcessor.TranslateBlockState(t, id,
                                                               bs.Data);

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

                if (state == null)
                {
                    state = ChunkProcessor.TranslateBlockState(
                        BlockFactory.GetBlockState(bs.Name),
                        -1, bs.Data);
                }

                if (state != null)
                {
                    BaseClient.WorldReceiver?.SetBlockState(
                        new BlockCoordinates(message.coordinates.X, message.coordinates.Y, message.coordinates.Z),
                        state);
                }

                /*
                 * var result =
                 *      BlockFactory.RuntimeIdTable.FirstOrDefault(xx => xx.Name == bs.Name);
                 *
                 * uint res = 0;
                 * bool ss = false;
                 * if (result != null && result.Id >= 0)
                 * {
                 *      res = BlockFactory.GetBlockStateID((int) result.Id, (byte) bs.Data);
                 *      ss = true;
                 * }
                 *
                 * if (ss && AnvilWorldProvider.BlockStateMapper.TryGetValue(res, out res))
                 * {
                 *      var a = BlockFactory.GetBlockState(res);
                 *      BaseClient.WorldReceiver?.SetBlockState(
                 *              new BlockCoordinates(message.coordinates.X, message.coordinates.Y, message.coordinates.Z),
                 *              a);
                 * }
                 * else
                 * {
                 *
                 *      BaseClient.WorldReceiver?.SetBlockState(
                 *              new BlockCoordinates(message.coordinates.X, message.coordinates.Y, message.coordinates.Z),
                 *              BlockFactory.GetBlockState(bs.Name));
                 * }*/
            }
            else
            {
                Log.Warn($"Received unknown block runtime id.");
            }
        }
Пример #7
0
 protected Block(int blockId, byte metadata) : this(BlockFactory.GetBlockStateID(blockId, metadata))
 {
 }