From c995f9c3a94a8206eceeddb83a76e2b88594d2ba Mon Sep 17 00:00:00 2001 From: emortaldev Date: Mon, 16 Jan 2023 23:57:18 +0000 Subject: [PATCH] Block event changes (#1675) * Add cursor position to interact events * Add block face to digging events * Expose interact position in interact event --- .../event/player/PlayerBlockBreakEvent.java | 15 +++++++++++- .../player/PlayerBlockInteractEvent.java | 2 +- .../player/PlayerEntityInteractEvent.java | 23 +++++++++++++++---- .../event/player/PlayerStartDiggingEvent.java | 15 +++++++++++- .../player/PlayerUseItemOnBlockEvent.java | 3 ++- .../minestom/server/instance/Instance.java | 3 ++- .../server/instance/InstanceContainer.java | 5 ++-- .../server/instance/SharedInstance.java | 5 ++-- .../server/instance/block/BlockHandler.java | 8 ++++++- .../listener/BlockPlacementListener.java | 9 +++++--- .../listener/PlayerDiggingListener.java | 21 +++++++++-------- .../server/listener/UseEntityListener.java | 7 ++++-- 12 files changed, 87 insertions(+), 29 deletions(-) diff --git a/src/main/java/net/minestom/server/event/player/PlayerBlockBreakEvent.java b/src/main/java/net/minestom/server/event/player/PlayerBlockBreakEvent.java index 6aecb0294..04edaf1be 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerBlockBreakEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerBlockBreakEvent.java @@ -6,6 +6,7 @@ import net.minestom.server.event.trait.BlockEvent; import net.minestom.server.event.trait.CancellableEvent; import net.minestom.server.event.trait.PlayerInstanceEvent; import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.block.BlockFace; import org.jetbrains.annotations.NotNull; public class PlayerBlockBreakEvent implements PlayerInstanceEvent, BlockEvent, CancellableEvent { @@ -14,16 +15,19 @@ public class PlayerBlockBreakEvent implements PlayerInstanceEvent, BlockEvent, C private final Block block; private Block resultBlock; private final Point blockPosition; + private final BlockFace blockFace; private boolean cancelled; public PlayerBlockBreakEvent(@NotNull Player player, - @NotNull Block block, @NotNull Block resultBlock, @NotNull Point blockPosition) { + @NotNull Block block, @NotNull Block resultBlock, @NotNull Point blockPosition, + @NotNull BlockFace blockFace) { this.player = player; this.block = block; this.resultBlock = resultBlock; this.blockPosition = blockPosition; + this.blockFace = blockFace; } /** @@ -45,6 +49,15 @@ public class PlayerBlockBreakEvent implements PlayerInstanceEvent, BlockEvent, C return resultBlock; } + /** + * Gets the face at which the block was broken + * + * @return the block face + */ + public @NotNull BlockFace getBlockFace() { + return blockFace; + } + /** * Changes the result of the event. * diff --git a/src/main/java/net/minestom/server/event/player/PlayerBlockInteractEvent.java b/src/main/java/net/minestom/server/event/player/PlayerBlockInteractEvent.java index 8921ce671..e664bbd29 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerBlockInteractEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerBlockInteractEvent.java @@ -30,7 +30,7 @@ public class PlayerBlockInteractEvent implements PlayerInstanceEvent, BlockEvent private boolean cancelled; public PlayerBlockInteractEvent(@NotNull Player player, @NotNull Player.Hand hand, - @NotNull Block block, @NotNull Point blockPosition, + @NotNull Block block, @NotNull Point blockPosition, @NotNull Point cursorPosition, @NotNull BlockFace blockFace) { this.player = player; this.hand = hand; diff --git a/src/main/java/net/minestom/server/event/player/PlayerEntityInteractEvent.java b/src/main/java/net/minestom/server/event/player/PlayerEntityInteractEvent.java index 265f215f7..e5901073f 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerEntityInteractEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerEntityInteractEvent.java @@ -1,5 +1,6 @@ package net.minestom.server.event.player; +import net.minestom.server.coordinate.Point; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Player; import net.minestom.server.event.trait.PlayerInstanceEvent; @@ -13,11 +14,19 @@ public class PlayerEntityInteractEvent implements PlayerInstanceEvent { private final Player player; private final Entity entityTarget; private final Player.Hand hand; + private final Point interactPosition; - public PlayerEntityInteractEvent(@NotNull Player player, @NotNull Entity entityTarget, @NotNull Player.Hand hand) { + public PlayerEntityInteractEvent(@NotNull Player player, @NotNull Entity entityTarget, @NotNull Player.Hand hand, + @NotNull Point interactPosition) { this.player = player; this.entityTarget = entityTarget; this.hand = hand; + this.interactPosition = interactPosition; + } + + @Override + public @NotNull Player getPlayer() { + return player; } /** @@ -40,8 +49,14 @@ public class PlayerEntityInteractEvent implements PlayerInstanceEvent { return hand; } - @Override - public @NotNull Player getPlayer() { - return player; + /** + * Gets the position at which the entity was interacted + * + * @see net.minestom.server.network.packet.client.play.ClientInteractEntityPacket.InteractAt + * @return the interaction position + */ + @NotNull + public Point getInteractPosition() { + return interactPosition; } } \ No newline at end of file diff --git a/src/main/java/net/minestom/server/event/player/PlayerStartDiggingEvent.java b/src/main/java/net/minestom/server/event/player/PlayerStartDiggingEvent.java index 8076c4ae8..f5c457602 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerStartDiggingEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerStartDiggingEvent.java @@ -6,6 +6,7 @@ import net.minestom.server.event.trait.BlockEvent; import net.minestom.server.event.trait.CancellableEvent; import net.minestom.server.event.trait.PlayerInstanceEvent; import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.block.BlockFace; import org.jetbrains.annotations.NotNull; /** @@ -21,13 +22,16 @@ public class PlayerStartDiggingEvent implements PlayerInstanceEvent, BlockEvent, private final Player player; private final Block block; private final Point blockPosition; + private final BlockFace blockFace; private boolean cancelled; - public PlayerStartDiggingEvent(@NotNull Player player, @NotNull Block block, @NotNull Point blockPosition) { + public PlayerStartDiggingEvent(@NotNull Player player, @NotNull Block block, @NotNull Point blockPosition, + @NotNull BlockFace blockFace) { this.player = player; this.block = block; this.blockPosition = blockPosition; + this.blockFace = blockFace; } /** @@ -49,6 +53,15 @@ public class PlayerStartDiggingEvent implements PlayerInstanceEvent, BlockEvent, return blockPosition; } + /** + * Gets the face you are digging + * + * @return the block face + */ + public @NotNull BlockFace getBlockFace() { + return blockFace; + } + @Override public boolean isCancelled() { return cancelled; diff --git a/src/main/java/net/minestom/server/event/player/PlayerUseItemOnBlockEvent.java b/src/main/java/net/minestom/server/event/player/PlayerUseItemOnBlockEvent.java index 5ff99abe5..a2a3d0548 100644 --- a/src/main/java/net/minestom/server/event/player/PlayerUseItemOnBlockEvent.java +++ b/src/main/java/net/minestom/server/event/player/PlayerUseItemOnBlockEvent.java @@ -21,7 +21,8 @@ public class PlayerUseItemOnBlockEvent implements PlayerInstanceEvent, ItemEvent public PlayerUseItemOnBlockEvent(@NotNull Player player, @NotNull Player.Hand hand, @NotNull ItemStack itemStack, - @NotNull Point position, @NotNull BlockFace blockFace) { + @NotNull Point position, @NotNull Point cursorPosition, + @NotNull BlockFace blockFace) { this.player = player; this.hand = hand; this.itemStack = itemStack; diff --git a/src/main/java/net/minestom/server/instance/Instance.java b/src/main/java/net/minestom/server/instance/Instance.java index 090a88b77..b7c5affa6 100644 --- a/src/main/java/net/minestom/server/instance/Instance.java +++ b/src/main/java/net/minestom/server/instance/Instance.java @@ -20,6 +20,7 @@ import net.minestom.server.event.EventNode; import net.minestom.server.event.instance.InstanceTickEvent; import net.minestom.server.event.trait.InstanceEvent; import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.block.BlockFace; import net.minestom.server.instance.block.BlockHandler; import net.minestom.server.instance.generator.Generator; import net.minestom.server.network.packet.server.play.BlockActionPacket; @@ -150,7 +151,7 @@ public abstract class Instance implements Block.Getter, Block.Setter, * @return true if the block has been broken, false if it has been cancelled */ @ApiStatus.Internal - public abstract boolean breakBlock(@NotNull Player player, @NotNull Point blockPosition); + public abstract boolean breakBlock(@NotNull Player player, @NotNull Point blockPosition, @NotNull BlockFace blockFace); /** * Forces the generation of a {@link Chunk}, even if no file and {@link ChunkGenerator} are defined. diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index ea4901a60..1c222f04d 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -11,6 +11,7 @@ import net.minestom.server.event.instance.InstanceChunkLoadEvent; import net.minestom.server.event.instance.InstanceChunkUnloadEvent; import net.minestom.server.event.player.PlayerBlockBreakEvent; import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.block.BlockFace; import net.minestom.server.instance.block.BlockHandler; import net.minestom.server.instance.block.rule.BlockPlacementRule; import net.minestom.server.instance.generator.Generator; @@ -175,7 +176,7 @@ public class InstanceContainer extends Instance { } @Override - public boolean breakBlock(@NotNull Player player, @NotNull Point blockPosition) { + public boolean breakBlock(@NotNull Player player, @NotNull Point blockPosition, @NotNull BlockFace blockFace) { final Chunk chunk = getChunkAt(blockPosition); Check.notNull(chunk, "You cannot break blocks in a null chunk!"); if (chunk.isReadOnly()) return false; @@ -190,7 +191,7 @@ public class InstanceContainer extends Instance { chunk.sendChunk(player); return false; } - PlayerBlockBreakEvent blockBreakEvent = new PlayerBlockBreakEvent(player, block, Block.AIR, blockPosition); + PlayerBlockBreakEvent blockBreakEvent = new PlayerBlockBreakEvent(player, block, Block.AIR, blockPosition, blockFace); EventDispatcher.call(blockBreakEvent); final boolean allowed = !blockBreakEvent.isCancelled(); if (allowed) { diff --git a/src/main/java/net/minestom/server/instance/SharedInstance.java b/src/main/java/net/minestom/server/instance/SharedInstance.java index efa345e94..d9c401268 100644 --- a/src/main/java/net/minestom/server/instance/SharedInstance.java +++ b/src/main/java/net/minestom/server/instance/SharedInstance.java @@ -3,6 +3,7 @@ package net.minestom.server.instance; import net.minestom.server.coordinate.Point; import net.minestom.server.entity.Player; import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.block.BlockFace; import net.minestom.server.instance.block.BlockHandler; import net.minestom.server.instance.generator.Generator; import org.jetbrains.annotations.NotNull; @@ -35,8 +36,8 @@ public class SharedInstance extends Instance { } @Override - public boolean breakBlock(@NotNull Player player, @NotNull Point blockPosition) { - return instanceContainer.breakBlock(player, blockPosition); + public boolean breakBlock(@NotNull Player player, @NotNull Point blockPosition, @NotNull BlockFace blockFace) { + return instanceContainer.breakBlock(player, blockPosition, blockFace); } @Override diff --git a/src/main/java/net/minestom/server/instance/block/BlockHandler.java b/src/main/java/net/minestom/server/instance/block/BlockHandler.java index a97c34fb7..f231664b4 100644 --- a/src/main/java/net/minestom/server/instance/block/BlockHandler.java +++ b/src/main/java/net/minestom/server/instance/block/BlockHandler.java @@ -194,14 +194,16 @@ public interface BlockHandler { private final Block block; private final Instance instance; private final Point blockPosition; + private final Point cursorPosition; private final Player player; private final Player.Hand hand; @ApiStatus.Internal - public Interaction(Block block, Instance instance, Point blockPosition, Player player, Player.Hand hand) { + public Interaction(Block block, Instance instance, Point blockPosition, Point cursorPosition, Player player, Player.Hand hand) { this.block = block; this.instance = instance; this.blockPosition = blockPosition; + this.cursorPosition = cursorPosition; this.player = player; this.hand = hand; } @@ -218,6 +220,10 @@ public interface BlockHandler { return blockPosition; } + public @NotNull Point getCursorPosition() { + return cursorPosition; + } + public @NotNull Player getPlayer() { return player; } diff --git a/src/main/java/net/minestom/server/listener/BlockPlacementListener.java b/src/main/java/net/minestom/server/listener/BlockPlacementListener.java index 0b5f955c6..6f4679b09 100644 --- a/src/main/java/net/minestom/server/listener/BlockPlacementListener.java +++ b/src/main/java/net/minestom/server/listener/BlockPlacementListener.java @@ -3,6 +3,7 @@ package net.minestom.server.listener; import net.minestom.server.MinecraftServer; import net.minestom.server.collision.CollisionUtils; import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Entity; import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; @@ -49,15 +50,17 @@ public class BlockPlacementListener { final ItemStack usedItem = player.getItemInHand(hand); final Block interactedBlock = instance.getBlock(blockPosition); + final Point cursorPosition = new Vec(packet.cursorPositionX(), packet.cursorPositionY(), packet.cursorPositionZ()); + // Interact at block // FIXME: onUseOnBlock - PlayerBlockInteractEvent playerBlockInteractEvent = new PlayerBlockInteractEvent(player, hand, interactedBlock, blockPosition, blockFace); + PlayerBlockInteractEvent playerBlockInteractEvent = new PlayerBlockInteractEvent(player, hand, interactedBlock, blockPosition, cursorPosition, blockFace); EventDispatcher.call(playerBlockInteractEvent); boolean blockUse = playerBlockInteractEvent.isBlockingItemUse(); if (!playerBlockInteractEvent.isCancelled()) { final var handler = interactedBlock.handler(); if (handler != null) { - blockUse |= !handler.onInteract(new BlockHandler.Interaction(interactedBlock, instance, blockPosition, player, hand)); + blockUse |= !handler.onInteract(new BlockHandler.Interaction(interactedBlock, instance, blockPosition, cursorPosition, player, hand)); } } if (blockUse) { @@ -68,7 +71,7 @@ public class BlockPlacementListener { final Material useMaterial = usedItem.material(); if (!useMaterial.isBlock()) { // Player didn't try to place a block but interacted with one - PlayerUseItemOnBlockEvent event = new PlayerUseItemOnBlockEvent(player, hand, usedItem, blockPosition, blockFace); + PlayerUseItemOnBlockEvent event = new PlayerUseItemOnBlockEvent(player, hand, usedItem, blockPosition, cursorPosition, blockFace); EventDispatcher.call(event); return; } diff --git a/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java b/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java index 733066519..56e24b2c3 100644 --- a/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java +++ b/src/main/java/net/minestom/server/listener/PlayerDiggingListener.java @@ -11,6 +11,7 @@ import net.minestom.server.event.player.PlayerStartDiggingEvent; import net.minestom.server.event.player.PlayerSwapItemEvent; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.block.BlockFace; import net.minestom.server.inventory.PlayerInventory; import net.minestom.server.item.ItemStack; import net.minestom.server.item.StackingRule; @@ -29,13 +30,13 @@ public final class PlayerDiggingListener { DiggingResult diggingResult = null; if (status == ClientPlayerDiggingPacket.Status.STARTED_DIGGING) { if (!instance.isChunkLoaded(blockPosition)) return; - diggingResult = startDigging(player, instance, blockPosition); + diggingResult = startDigging(player, instance, blockPosition, packet.blockFace()); } else if (status == ClientPlayerDiggingPacket.Status.CANCELLED_DIGGING) { if (!instance.isChunkLoaded(blockPosition)) return; diggingResult = cancelDigging(instance, blockPosition); } else if (status == ClientPlayerDiggingPacket.Status.FINISHED_DIGGING) { if (!instance.isChunkLoaded(blockPosition)) return; - diggingResult = finishDigging(player, instance, blockPosition); + diggingResult = finishDigging(player, instance, blockPosition, packet.blockFace()); } else if (status == ClientPlayerDiggingPacket.Status.DROP_ITEM_STACK) { dropStack(player); } else if (status == ClientPlayerDiggingPacket.Status.DROP_ITEM) { @@ -51,7 +52,7 @@ public final class PlayerDiggingListener { } } - private static DiggingResult startDigging(Player player, Instance instance, Point blockPosition) { + private static DiggingResult startDigging(Player player, Instance instance, Point blockPosition, BlockFace blockFace) { final Block block = instance.getBlock(blockPosition); final GameMode gameMode = player.getGameMode(); @@ -61,19 +62,19 @@ public final class PlayerDiggingListener { } if (gameMode == GameMode.CREATIVE) { - return breakBlock(instance, player, blockPosition, block); + return breakBlock(instance, player, blockPosition, block, blockFace); } // Survival digging // FIXME: verify mineable tag and enchantment final boolean instantBreak = player.isInstantBreak() || block.registry().hardness() == 0; if (!instantBreak) { - PlayerStartDiggingEvent playerStartDiggingEvent = new PlayerStartDiggingEvent(player, block, blockPosition); + PlayerStartDiggingEvent playerStartDiggingEvent = new PlayerStartDiggingEvent(player, block, blockPosition, blockFace); EventDispatcher.call(playerStartDiggingEvent); return new DiggingResult(block, !playerStartDiggingEvent.isCancelled()); } // Client only send a single STARTED_DIGGING when insta-break is enabled - return breakBlock(instance, player, blockPosition, block); + return breakBlock(instance, player, blockPosition, block, blockFace); } private static DiggingResult cancelDigging(Instance instance, Point blockPosition) { @@ -81,14 +82,14 @@ public final class PlayerDiggingListener { return new DiggingResult(block, true); } - private static DiggingResult finishDigging(Player player, Instance instance, Point blockPosition) { + private static DiggingResult finishDigging(Player player, Instance instance, Point blockPosition, BlockFace blockFace) { final Block block = instance.getBlock(blockPosition); if (shouldPreventBreaking(player, block)) { return new DiggingResult(block, false); } - return breakBlock(instance, player, blockPosition, block); + return breakBlock(instance, player, blockPosition, block, blockFace); } private static boolean shouldPreventBreaking(@NotNull Player player, Block block) { @@ -155,9 +156,9 @@ public final class PlayerDiggingListener { private static DiggingResult breakBlock(Instance instance, Player player, - Point blockPosition, Block previousBlock) { + Point blockPosition, Block previousBlock, BlockFace blockFace) { // Unverified block break, client is fully responsible - final boolean success = instance.breakBlock(player, blockPosition); + final boolean success = instance.breakBlock(player, blockPosition, blockFace); final Block updatedBlock = instance.getBlock(blockPosition); if (!success) { if (previousBlock.isSolid()) { diff --git a/src/main/java/net/minestom/server/listener/UseEntityListener.java b/src/main/java/net/minestom/server/listener/UseEntityListener.java index 0710da3dd..8040d7591 100644 --- a/src/main/java/net/minestom/server/listener/UseEntityListener.java +++ b/src/main/java/net/minestom/server/listener/UseEntityListener.java @@ -1,5 +1,7 @@ package net.minestom.server.listener; +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Entity; import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.Player; @@ -12,7 +14,7 @@ public class UseEntityListener { public static void useEntityListener(ClientInteractEntityPacket packet, Player player) { final Entity entity = Entity.getEntity(packet.targetId()); - if (entity == null || !entity.isViewer(player) || player.getDistance(entity) > 6) + if (entity == null || !entity.isViewer(player) || player.getDistanceSquared(entity) > 6 * 6) return; ClientInteractEntityPacket.Type type = packet.type(); @@ -21,7 +23,8 @@ public class UseEntityListener { return; EventDispatcher.call(new EntityAttackEvent(player, entity)); } else if (type instanceof ClientInteractEntityPacket.InteractAt interactAt) { - EventDispatcher.call(new PlayerEntityInteractEvent(player, entity, interactAt.hand())); + Point interactPosition = new Vec(interactAt.targetX(), interactAt.targetY(), interactAt.targetZ()); + EventDispatcher.call(new PlayerEntityInteractEvent(player, entity, interactAt.hand(), interactPosition)); } } }