diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerUseBowWithoutProjectileEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerUseBowWithoutProjectileEvent.java new file mode 100644 index 000000000000..1f7d3cd5b664 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerUseBowWithoutProjectileEvent.java @@ -0,0 +1,61 @@ +package io.papermc.paper.event.player; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Called when a player tries to draw a bow or load a crossbow without having a suitable projectile item in their inventory + */ +@NullMarked +public class PlayerUseBowWithoutProjectileEvent extends PlayerEvent { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final ItemStack weapon; + private ItemStack projectileItem; + + @ApiStatus.Internal + public PlayerUseBowWithoutProjectileEvent(final Player player, final ItemStack weapon) { + super(player); + this.weapon = weapon; + this.projectileItem = ItemStack.empty(); + } + + /** + * @return The weapon wich the player tries to use + */ + public ItemStack getWeapon() { + return weapon.clone(); + } + + /** + * @return The projectile that should be used + */ + public ItemStack getProjectileItem() { + return projectileItem.clone(); + } + + /** + * Sets the projectile that should be used + *
+ * Note: setting this to {@link ItemStack#empty()} will prevent the player from using the bow/crossbow + * + * @param projectile the projectile + */ + public void setProjectileItem(ItemStack projectile) { + this.projectileItem = projectile.clone(); + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch index 4d20a5178a80..2281e7958e04 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/player/Player.java.patch @@ -669,3 +669,20 @@ for (int i = 0; i < this.inventory.getContainerSize(); i++) { ItemStack item = this.inventory.getItem(i); +@@ -2007,7 +_,15 @@ + } + } + +- return this.abilities.instabuild ? new ItemStack(Items.ARROW) : ItemStack.EMPTY; ++ // Paper start - PlayerUseBowWithoutProjectileEvent ++ if (this.abilities.instabuild) { ++ return new ItemStack(Items.ARROW); ++ } else { ++ io.papermc.paper.event.player.PlayerUseBowWithoutProjectileEvent event = new io.papermc.paper.event.player.PlayerUseBowWithoutProjectileEvent((org.bukkit.entity.Player) getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(shootable)); ++ event.callEvent(); ++ return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getProjectileItem()); ++ } ++ // Paper end - PlayerUseBowWithoutProjectileEvent + } + } + }