minecraft_25w45a_unobfuscated/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
2025-11-24 22:52:51 +03:00

160 lines
6.9 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.google.common.collect.Lists
* io.netty.buffer.ByteBuf
* io.netty.buffer.Unpooled
* org.jspecify.annotations.Nullable
*/
package net.minecraft.network.protocol.game;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.levelgen.Heightmap;
import org.jspecify.annotations.Nullable;
public class ClientboundLevelChunkPacketData {
private static final StreamCodec<ByteBuf, Map<Heightmap.Types, long[]>> HEIGHTMAPS_STREAM_CODEC = ByteBufCodecs.map(size -> new EnumMap(Heightmap.Types.class), Heightmap.Types.STREAM_CODEC, ByteBufCodecs.LONG_ARRAY);
private static final int TWO_MEGABYTES = 0x200000;
private final Map<Heightmap.Types, long[]> heightmaps;
private final byte[] buffer;
private final List<BlockEntityInfo> blockEntitiesData;
public ClientboundLevelChunkPacketData(LevelChunk levelChunk) {
this.heightmaps = levelChunk.getHeightmaps().stream().filter(entry -> ((Heightmap.Types)entry.getKey()).sendToClient()).collect(Collectors.toMap(Map.Entry::getKey, entry -> (long[])((Heightmap)entry.getValue()).getRawData().clone()));
this.buffer = new byte[ClientboundLevelChunkPacketData.calculateChunkSize(levelChunk)];
ClientboundLevelChunkPacketData.extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk);
this.blockEntitiesData = Lists.newArrayList();
for (Map.Entry<BlockPos, BlockEntity> entry2 : levelChunk.getBlockEntities().entrySet()) {
this.blockEntitiesData.add(BlockEntityInfo.create(entry2.getValue()));
}
}
public ClientboundLevelChunkPacketData(RegistryFriendlyByteBuf input, int x, int z) {
this.heightmaps = (Map)HEIGHTMAPS_STREAM_CODEC.decode(input);
int size = input.readVarInt();
if (size > 0x200000) {
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
}
this.buffer = new byte[size];
input.readBytes(this.buffer);
this.blockEntitiesData = (List)BlockEntityInfo.LIST_STREAM_CODEC.decode(input);
}
public void write(RegistryFriendlyByteBuf output) {
HEIGHTMAPS_STREAM_CODEC.encode(output, this.heightmaps);
output.writeVarInt(this.buffer.length);
output.writeBytes(this.buffer);
BlockEntityInfo.LIST_STREAM_CODEC.encode(output, this.blockEntitiesData);
}
private static int calculateChunkSize(LevelChunk chunk) {
int total = 0;
for (LevelChunkSection section : chunk.getSections()) {
total += section.getSerializedSize();
}
return total;
}
private ByteBuf getWriteBuffer() {
ByteBuf buffer = Unpooled.wrappedBuffer((byte[])this.buffer);
buffer.writerIndex(0);
return buffer;
}
public static void extractChunkData(FriendlyByteBuf buffer, LevelChunk chunk) {
for (LevelChunkSection section : chunk.getSections()) {
section.write(buffer);
}
if (buffer.writerIndex() != buffer.capacity()) {
throw new IllegalStateException("Didn't fill chunk buffer: expected " + buffer.capacity() + " bytes, got " + buffer.writerIndex());
}
}
public Consumer<BlockEntityTagOutput> getBlockEntitiesTagsConsumer(int x, int z) {
return output -> this.getBlockEntitiesTags((BlockEntityTagOutput)output, x, z);
}
private void getBlockEntitiesTags(BlockEntityTagOutput output, int x, int z) {
int baseX = 16 * x;
int baseZ = 16 * z;
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
for (BlockEntityInfo data : this.blockEntitiesData) {
int unpackedX = baseX + SectionPos.sectionRelative(data.packedXZ >> 4);
int unpackedZ = baseZ + SectionPos.sectionRelative(data.packedXZ);
pos.set(unpackedX, data.y, unpackedZ);
output.accept(pos, data.type, data.tag);
}
}
public FriendlyByteBuf getReadBuffer() {
return new FriendlyByteBuf(Unpooled.wrappedBuffer((byte[])this.buffer));
}
public Map<Heightmap.Types, long[]> getHeightmaps() {
return this.heightmaps;
}
private static class BlockEntityInfo {
public static final StreamCodec<RegistryFriendlyByteBuf, BlockEntityInfo> STREAM_CODEC = StreamCodec.ofMember(BlockEntityInfo::write, BlockEntityInfo::new);
public static final StreamCodec<RegistryFriendlyByteBuf, List<BlockEntityInfo>> LIST_STREAM_CODEC = STREAM_CODEC.apply(ByteBufCodecs.list());
private final int packedXZ;
private final int y;
private final BlockEntityType<?> type;
private final @Nullable CompoundTag tag;
private BlockEntityInfo(int packedXZ, int y, BlockEntityType<?> type, @Nullable CompoundTag tag) {
this.packedXZ = packedXZ;
this.y = y;
this.type = type;
this.tag = tag;
}
private BlockEntityInfo(RegistryFriendlyByteBuf input) {
this.packedXZ = input.readByte();
this.y = input.readShort();
this.type = (BlockEntityType)ByteBufCodecs.registry(Registries.BLOCK_ENTITY_TYPE).decode(input);
this.tag = input.readNbt();
}
private void write(RegistryFriendlyByteBuf output) {
output.writeByte(this.packedXZ);
output.writeShort(this.y);
ByteBufCodecs.registry(Registries.BLOCK_ENTITY_TYPE).encode(output, this.type);
output.writeNbt(this.tag);
}
private static BlockEntityInfo create(BlockEntity blockEntity) {
CompoundTag tag = blockEntity.getUpdateTag(blockEntity.getLevel().registryAccess());
BlockPos pos = blockEntity.getBlockPos();
int xz = SectionPos.sectionRelative(pos.getX()) << 4 | SectionPos.sectionRelative(pos.getZ());
return new BlockEntityInfo(xz, pos.getY(), blockEntity.getType(), tag.isEmpty() ? null : tag);
}
}
@FunctionalInterface
public static interface BlockEntityTagOutput {
public void accept(BlockPos var1, BlockEntityType<?> var2, @Nullable CompoundTag var3);
}
}