Search in sources :

Example 1 with BitStorage

use of net.minecraft.util.BitStorage in project Denizen-For-Bukkit by DenizenScript.

the class FakeBlockHelper method handleMapChunkPacket.

public static ClientboundLevelChunkPacket handleMapChunkPacket(ClientboundLevelChunkPacket originalPacket, List<FakeBlock> blocks) {
    try {
        ClientboundLevelChunkPacket packet = new ClientboundLevelChunkPacket(DenizenNetworkManagerImpl.copyPacket(originalPacket));
        copyPacketPaperPatch(packet, originalPacket);
        // TODO: properly update HeightMap?
        BitSet bitmask = packet.getAvailableSections();
        FriendlyByteBuf serial = originalPacket.getReadBuffer();
        FriendlyByteBuf outputSerial = new FriendlyByteBuf(Unpooled.buffer(serial.readableBytes()));
        List<net.minecraft.nbt.CompoundTag> blockEntities = new ArrayList<>(packet.getBlockEntitiesTags());
        BLOCKENTITIES_MAPCHUNK.set(packet, blockEntities);
        ListIterator<CompoundTag> iterator = blockEntities.listIterator();
        while (iterator.hasNext()) {
            net.minecraft.nbt.CompoundTag blockEnt = iterator.next();
            int x = blockEnt.getInt("x");
            int y = blockEnt.getInt("y");
            int z = blockEnt.getInt("z");
            for (FakeBlock block : blocks) {
                LocationTag loc = block.location;
                if (loc.getBlockX() == x && loc.getBlockY() == y && loc.getBlockZ() == z && block.material != null) {
                    iterator.remove();
                    break;
                }
            }
        }
        for (FakeBlock block : blocks) {
            if (block.material != null) {
                LocationTag loc = block.location;
                net.minecraft.nbt.CompoundTag newCompound = new net.minecraft.nbt.CompoundTag();
                newCompound.putInt("x", loc.getBlockX());
                newCompound.putInt("y", loc.getBlockY());
                newCompound.putInt("z", loc.getBlockZ());
                newCompound.putString("id", block.material.getMaterial().getKey().toString());
                blockEntities.add(newCompound);
            }
        }
        for (int y = 0; y < 16; y++) {
            if (bitmask.get(y)) {
                int blockCount = serial.readShort();
                int width = serial.readUnsignedByte();
                int paletteLen = serial.readVarInt();
                int[] palette = new int[paletteLen];
                for (int p = 0; p < paletteLen; p++) {
                    palette[p] = serial.readVarInt();
                }
                int dataLen = serial.readVarInt();
                long[] blockListHelper = new long[dataLen];
                for (int i = 0; i < blockListHelper.length; i++) {
                    blockListHelper[i] = serial.readLong();
                }
                outputSerial.writeShort(blockCount);
                if (!anyBlocksInSection(blocks, y)) {
                    outputSerial.writeByte(width);
                    outputSerial.writeVarInt(paletteLen);
                    for (int p = 0; p < paletteLen; p++) {
                        outputSerial.writeVarInt(palette[p]);
                    }
                    outputSerial.writeLongArray(blockListHelper);
                    continue;
                }
                char dataBitsF = (char) (64 / width);
                int expectedLength = (4096 + dataBitsF - 1) / dataBitsF;
                if (blockListHelper.length != expectedLength) {
                    // This chunk is too-complex and is using non-standard chunk format. For now, just ignore it.
                    return originalPacket;
                // TODO: Add support for processing very-complex chunks (DataPaletteHash might be responsible for the unique format?)
                }
                BitStorage bits = new BitStorage(width, 4096, blockListHelper);
                int minY = y << 4;
                int maxY = (y << 4) + 16;
                for (FakeBlock block : blocks) {
                    if (block.material != null) {
                        int blockY = block.location.getBlockY();
                        if (blockY >= minY && blockY < maxY) {
                            int blockX = block.location.getBlockX();
                            int blockZ = block.location.getBlockZ();
                            blockX -= (blockX >> 4) * 16;
                            blockY -= (blockY >> 4) * 16;
                            blockZ -= (blockZ >> 4) * 16;
                            int blockIndex = blockArrayIndex(blockX, blockY, blockZ);
                            BlockState replacementData = getNMSState(block);
                            int globalPaletteIndex = indexInPalette(replacementData);
                            int subPaletteId = getPaletteSubId(palette, globalPaletteIndex);
                            if (subPaletteId == -1) {
                                int[] newPalette = new int[paletteLen + 1];
                                if (paletteLen >= 0)
                                    System.arraycopy(palette, 0, newPalette, 0, paletteLen);
                                newPalette[paletteLen] = globalPaletteIndex;
                                subPaletteId = paletteLen;
                                paletteLen++;
                                palette = newPalette;
                                int newWidth = Mth.ceillog2(paletteLen);
                                if (newWidth > width) {
                                    BitStorage newBits = new BitStorage(newWidth, 4096);
                                    for (int i = 0; i < bits.getSize(); i++) {
                                        newBits.getAndSet(i, bits.get(i));
                                    }
                                    bits = newBits;
                                    width = newWidth;
                                }
                            }
                            bits.getAndSet(blockIndex, subPaletteId);
                        }
                    }
                }
                outputSerial.writeByte(width);
                outputSerial.writeVarInt(paletteLen);
                for (int p = 0; p < palette.length; p++) {
                    outputSerial.writeVarInt(palette[p]);
                }
                outputSerial.writeLongArray(bits.getRaw());
            }
        }
        int[] biomes = packet.getBiomes();
        if (biomes != null) {
            outputSerial.writeVarIntArray(biomes);
        }
        byte[] outputBytes = outputSerial.array();
        DATA_MAPCHUNK.set(packet, outputBytes);
        return packet;
    } catch (Exception ex) {
        Debug.echoError(ex);
    }
    return null;
}
Also used : FriendlyByteBuf(net.minecraft.network.FriendlyByteBuf) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) FakeBlock(com.denizenscript.denizen.utilities.blocks.FakeBlock) LocationTag(com.denizenscript.denizen.objects.LocationTag) CompoundTag(net.minecraft.nbt.CompoundTag) BlockState(net.minecraft.world.level.block.state.BlockState) ClientboundLevelChunkPacket(net.minecraft.network.protocol.game.ClientboundLevelChunkPacket) CompoundTag(net.minecraft.nbt.CompoundTag) BitStorage(net.minecraft.util.BitStorage)

Aggregations

LocationTag (com.denizenscript.denizen.objects.LocationTag)1 FakeBlock (com.denizenscript.denizen.utilities.blocks.FakeBlock)1 ArrayList (java.util.ArrayList)1 BitSet (java.util.BitSet)1 CompoundTag (net.minecraft.nbt.CompoundTag)1 FriendlyByteBuf (net.minecraft.network.FriendlyByteBuf)1 ClientboundLevelChunkPacket (net.minecraft.network.protocol.game.ClientboundLevelChunkPacket)1 BitStorage (net.minecraft.util.BitStorage)1 BlockState (net.minecraft.world.level.block.state.BlockState)1