diff --git a/paper-api/src/main/java/org/bukkit/block/ChiseledBookshelf.java b/paper-api/src/main/java/org/bukkit/block/ChiseledBookshelf.java
index 4cae298f18..1cc5c2021c 100644
--- a/paper-api/src/main/java/org/bukkit/block/ChiseledBookshelf.java
+++ b/paper-api/src/main/java/org/bukkit/block/ChiseledBookshelf.java
@@ -2,6 +2,7 @@ package org.bukkit.block;
import org.bukkit.inventory.BlockInventoryHolder;
import org.bukkit.inventory.ChiseledBookshelfInventory;
+import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
/**
@@ -37,4 +38,16 @@ public interface ChiseledBookshelf extends TileState, BlockInventoryHolder {
*/
@NotNull
ChiseledBookshelfInventory getSnapshotInventory();
+
+ /**
+ * Gets the appropriate slot based on a vector relative to this block.
+ * Will return -1 if the given vector is not within the bounds of any slot.
+ *
+ * The supplied vector should only contain components with values between 0.0 + * and 1.0, inclusive. + * + * @param position a vector relative to this block + * @return the slot under the given vector or -1 + */ + int getSlot(@NotNull Vector position); } diff --git a/paper-api/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java b/paper-api/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java index 1208e1f8c2..ed72095b5c 100644 --- a/paper-api/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/player/PlayerInteractEvent.java @@ -10,6 +10,7 @@ import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockCanBuildEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,18 +35,24 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable { private Result useClickedBlock; private Result useItemInHand; private EquipmentSlot hand; + private Vector clickedPosistion; public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace) { this(who, action, item, clickedBlock, clickedFace, EquipmentSlot.HAND); } public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace, @Nullable final EquipmentSlot hand) { + this(who, action, item, clickedBlock, clickedFace, hand, null); + } + + public PlayerInteractEvent(@NotNull final Player who, @NotNull final Action action, @Nullable final ItemStack item, @Nullable final Block clickedBlock, @NotNull final BlockFace clickedFace, @Nullable final EquipmentSlot hand, @Nullable final Vector clickedPosition) { super(who); this.action = action; this.item = item; this.blockClicked = clickedBlock; this.blockFace = clickedFace; this.hand = hand; + this.clickedPosistion = clickedPosition; useItemInHand = Result.DEFAULT; useClickedBlock = clickedBlock == null ? Result.DENY : Result.ALLOW; @@ -221,6 +228,19 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable { return hand; } + /** + * Gets the exact position on the block the player interacted with, this will + * be null outside of {@link Action#RIGHT_CLICK_BLOCK}. + *
+ * All vector components are between 0.0 and 1.0 inclusive. + * + * @return the clicked position. May be null. + */ + @Nullable + public Vector getClickedPosition() { + return clickedPosistion; + } + @NotNull @Override public HandlerList getHandlers() {