From 95ac82cf733c3bc436f32f3582096e8de6c3f0f4 Mon Sep 17 00:00:00 2001 From: Moulberry Date: Thu, 21 Sep 2023 15:22:34 +0800 Subject: [PATCH] Increase protocol version to 6, implement PlayerInteractEvent in SetBlockPacketListener --- .../com/moulberry/axiom/AxiomConstants.java | 2 +- .../axiom/packet/SetBlockPacketListener.java | 192 +++++++++++------- 2 files changed, 117 insertions(+), 77 deletions(-) diff --git a/src/main/java/com/moulberry/axiom/AxiomConstants.java b/src/main/java/com/moulberry/axiom/AxiomConstants.java index f553d14..d0da771 100644 --- a/src/main/java/com/moulberry/axiom/AxiomConstants.java +++ b/src/main/java/com/moulberry/axiom/AxiomConstants.java @@ -12,7 +12,7 @@ public class AxiomConstants { } } - public static final int API_VERSION = 5; + public static final int API_VERSION = 6; public static final NamespacedKey ACTIVE_HOTBAR_INDEX = new NamespacedKey("axiom", "active_hotbar_index"); public static final NamespacedKey HOTBAR_DATA = new NamespacedKey("axiom", "hotbar_data"); diff --git a/src/main/java/com/moulberry/axiom/packet/SetBlockPacketListener.java b/src/main/java/com/moulberry/axiom/packet/SetBlockPacketListener.java index f1a5c7c..a8e417d 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetBlockPacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetBlockPacketListener.java @@ -8,6 +8,8 @@ import net.minecraft.core.SectionPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; @@ -16,9 +18,14 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.lighting.LightEngine; +import net.minecraft.world.phys.BlockHitResult; import org.bukkit.Bukkit; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlock; import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; import org.bukkit.entity.Player; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.plugin.messaging.PluginMessageListener; import org.jetbrains.annotations.NotNull; import xyz.jpenilla.reflectionremapper.ReflectionRemapper; @@ -61,97 +68,130 @@ public class SetBlockPacketListener implements PluginMessageListener { // Read packet FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message)); - BlockPos blockPos = friendlyByteBuf.readBlockPos(); - BlockState blockState = friendlyByteBuf.readById(Block.BLOCK_STATE_REGISTRY); + Map blocks = friendlyByteBuf.readMap(FriendlyByteBuf::readBlockPos, buf -> buf.readById(Block.BLOCK_STATE_REGISTRY)); boolean updateNeighbors = friendlyByteBuf.readBoolean(); - int sequenceId = friendlyByteBuf.readInt(); + + int reason = friendlyByteBuf.readVarInt(); + boolean breaking = friendlyByteBuf.readBoolean(); + BlockHitResult blockHit = friendlyByteBuf.readBlockHitResult(); + InteractionHand hand = friendlyByteBuf.readEnum(InteractionHand.class); + int sequenceId = friendlyByteBuf.readVarInt(); ServerPlayer player = ((CraftPlayer)bukkitPlayer).getHandle(); + org.bukkit.inventory.ItemStack heldItem; + if (hand == InteractionHand.MAIN_HAND) { + heldItem = bukkitPlayer.getInventory().getItemInMainHand(); + } else { + heldItem = bukkitPlayer.getInventory().getItemInOffHand(); + } + + org.bukkit.block.Block blockClicked = bukkitPlayer.getWorld().getBlockAt(blockHit.getBlockPos().getX(), + blockHit.getBlockPos().getY(), blockHit.getBlockPos().getZ()); + + BlockFace blockFace = CraftBlock.notchToBlockFace(blockHit.getDirection()); + + // Call interact event + PlayerInteractEvent playerInteractEvent = new PlayerInteractEvent(bukkitPlayer, + breaking ? Action.LEFT_CLICK_BLOCK : Action.RIGHT_CLICK_BLOCK, heldItem, blockClicked, blockFace); + if (!playerInteractEvent.callEvent()) { + if (sequenceId >= 0) { + player.connection.ackBlockChangesUpTo(sequenceId); + } + return; + } + // Update blocks if (updateNeighbors) { - player.level().setBlock(blockPos, blockState, 3); + for (Map.Entry entry : blocks.entrySet()) { + player.level().setBlock(entry.getKey(), entry.getValue(), 3); + } } else { - int bx = blockPos.getX(); - int by = blockPos.getY(); - int bz = blockPos.getZ(); - int x = bx & 0xF; - int y = by & 0xF; - int z = bz & 0xF; - int cx = bx >> 4; - int cy = by >> 4; - int cz = bz >> 4; + for (Map.Entry entry : blocks.entrySet()) { + BlockPos blockPos = entry.getKey(); + BlockState blockState = entry.getValue(); - ServerLevel level = player.serverLevel(); - LevelChunk chunk = level.getChunk(cx, cz); - chunk.setUnsaved(true); + int bx = blockPos.getX(); + int by = blockPos.getY(); + int bz = blockPos.getZ(); + int x = bx & 0xF; + int y = by & 0xF; + int z = bz & 0xF; + int cx = bx >> 4; + int cy = by >> 4; + int cz = bz >> 4; - LevelChunkSection section = chunk.getSection(level.getSectionIndexFromSectionY(cy)); - boolean hasOnlyAir = section.hasOnlyAir(); + ServerLevel level = player.serverLevel(); + LevelChunk chunk = level.getChunk(cx, cz); + chunk.setUnsaved(true); - Heightmap worldSurface = null; - Heightmap oceanFloor = null; - Heightmap motionBlocking = null; - Heightmap motionBlockingNoLeaves = null; - for (Map.Entry heightmap : chunk.getHeightmaps()) { - switch (heightmap.getKey()) { - case WORLD_SURFACE -> worldSurface = heightmap.getValue(); - case OCEAN_FLOOR -> oceanFloor = heightmap.getValue(); - case MOTION_BLOCKING -> motionBlocking = heightmap.getValue(); - case MOTION_BLOCKING_NO_LEAVES -> motionBlockingNoLeaves = heightmap.getValue(); - default -> {} - } - } + LevelChunkSection section = chunk.getSection(level.getSectionIndexFromSectionY(cy)); + boolean hasOnlyAir = section.hasOnlyAir(); - BlockState old = section.setBlockState(x, y, z, blockState, false); - if (blockState != old) { - Block block = blockState.getBlock(); - motionBlocking.update(x, by, z, blockState); - motionBlockingNoLeaves.update(x, by, z, blockState); - oceanFloor.update(x, by, z, blockState); - worldSurface.update(x, by, z, blockState); - - if (blockState.hasBlockEntity()) { - BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); - - if (blockEntity == null) { - // There isn't a block entity here, create it! - blockEntity = ((EntityBlock)block).newBlockEntity(blockPos, blockState); - if (blockEntity != null) { - chunk.addAndRegisterBlockEntity(blockEntity); - } - } else if (blockEntity.getType().isValid(blockState)) { - // Block entity is here and the type is correct - // Just update the state and ticker and move on - blockEntity.setBlockState(blockState); - - try { - this.updateBlockEntityTicker.invoke(chunk, blockEntity); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } else { - // Block entity type isn't correct, we need to recreate it - chunk.removeBlockEntity(blockPos); - - blockEntity = ((EntityBlock)block).newBlockEntity(blockPos, blockState); - if (blockEntity != null) { - chunk.addAndRegisterBlockEntity(blockEntity); - } + Heightmap worldSurface = null; + Heightmap oceanFloor = null; + Heightmap motionBlocking = null; + Heightmap motionBlockingNoLeaves = null; + for (Map.Entry heightmap : chunk.getHeightmaps()) { + switch (heightmap.getKey()) { + case WORLD_SURFACE -> worldSurface = heightmap.getValue(); + case OCEAN_FLOOR -> oceanFloor = heightmap.getValue(); + case MOTION_BLOCKING -> motionBlocking = heightmap.getValue(); + case MOTION_BLOCKING_NO_LEAVES -> motionBlockingNoLeaves = heightmap.getValue(); + default -> {} } - } else if (old.hasBlockEntity()) { - chunk.removeBlockEntity(blockPos); } - level.getChunkSource().blockChanged(blockPos); - if (LightEngine.hasDifferentLightProperties(chunk, blockPos, old, blockState)) { - level.getChunkSource().getLightEngine().checkBlock(blockPos); - } - } + BlockState old = section.setBlockState(x, y, z, blockState, false); + if (blockState != old) { + Block block = blockState.getBlock(); + motionBlocking.update(x, by, z, blockState); + motionBlockingNoLeaves.update(x, by, z, blockState); + oceanFloor.update(x, by, z, blockState); + worldSurface.update(x, by, z, blockState); - boolean nowHasOnlyAir = section.hasOnlyAir(); - if (hasOnlyAir != nowHasOnlyAir) { - level.getChunkSource().getLightEngine().updateSectionStatus(SectionPos.of(cx, cy, cz), nowHasOnlyAir); + if (blockState.hasBlockEntity()) { + BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK); + + if (blockEntity == null) { + // There isn't a block entity here, create it! + blockEntity = ((EntityBlock)block).newBlockEntity(blockPos, blockState); + if (blockEntity != null) { + chunk.addAndRegisterBlockEntity(blockEntity); + } + } else if (blockEntity.getType().isValid(blockState)) { + // Block entity is here and the type is correct + // Just update the state and ticker and move on + blockEntity.setBlockState(blockState); + + try { + this.updateBlockEntityTicker.invoke(chunk, blockEntity); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } else { + // Block entity type isn't correct, we need to recreate it + chunk.removeBlockEntity(blockPos); + + blockEntity = ((EntityBlock)block).newBlockEntity(blockPos, blockState); + if (blockEntity != null) { + chunk.addAndRegisterBlockEntity(blockEntity); + } + } + } else if (old.hasBlockEntity()) { + chunk.removeBlockEntity(blockPos); + } + + level.getChunkSource().blockChanged(blockPos); + if (LightEngine.hasDifferentLightProperties(chunk, blockPos, old, blockState)) { + level.getChunkSource().getLightEngine().checkBlock(blockPos); + } + } + + boolean nowHasOnlyAir = section.hasOnlyAir(); + if (hasOnlyAir != nowHasOnlyAir) { + level.getChunkSource().getLightEngine().updateSectionStatus(SectionPos.of(cx, cy, cz), nowHasOnlyAir); + } } }