diff --git a/Spigot-API-Patches/0115-PlayerReadyArrowEvent.patch b/Spigot-API-Patches/0115-PlayerReadyArrowEvent.patch new file mode 100644 index 0000000000..ebaaac60e1 --- /dev/null +++ b/Spigot-API-Patches/0115-PlayerReadyArrowEvent.patch @@ -0,0 +1,105 @@ +From 464e3985e5e2c29198f15414c94c9abb75d8aed3 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 18 Jun 2018 01:09:27 -0400 +Subject: [PATCH] PlayerReadyArrowEvent + +Called when a player is firing a bow and the server is choosing an arrow to use. +Plugins can skip selection of certain arrows and control which is used. + +diff --git a/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java b/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java +new file mode 100644 +index 00000000..c6add1b1 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/event/player/PlayerReadyArrowEvent.java +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining ++ * a copy of this software and associated documentation files (the ++ * "Software"), to deal in the Software without restriction, including ++ * without limitation the rights to use, copy, modify, merge, publish, ++ * distribute, sublicense, and/or sell copies of the Software, and to ++ * permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ++ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ++ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++package com.destroystokyo.paper.event.player; ++ ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.player.PlayerEvent; ++import org.bukkit.inventory.ItemStack; ++ ++/** ++ * Called when a player is firing a bow and the server is choosing an arrow to use. ++ */ ++public class PlayerReadyArrowEvent extends PlayerEvent implements Cancellable { ++ private final ItemStack bow; ++ private final ItemStack arrow; ++ ++ public PlayerReadyArrowEvent(Player player, ItemStack bow, ItemStack arrow) { ++ super(player); ++ this.bow = bow; ++ this.arrow = arrow; ++ } ++ ++ /** ++ * What bow the player is using to fire the arrow ++ */ ++ public ItemStack getBow() { ++ return bow; ++ } ++ ++ /** ++ * What arrow is being attempted to use ++ */ ++ public ItemStack getArrow() { ++ return arrow; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++ ++ private boolean cancelled = false; ++ ++ /** ++ * Whether or not use of this arrow is cancelled. On cancel, the server will try the next arrow available and fire another event. ++ */ ++ @Override ++ public boolean isCancelled() { ++ return cancelled; ++ } ++ ++ /** ++ * Cancel use of this arrow. On cancel, the server will try the next arrow available and fire another event. ++ * @param cancel true if you wish to cancel this event ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ cancelled = cancel; ++ } ++} +-- +2.17.1 + diff --git a/Spigot-Server-Patches/0312-PlayerReadyArrowEvent.patch b/Spigot-Server-Patches/0312-PlayerReadyArrowEvent.patch new file mode 100644 index 0000000000..7bce697b0a --- /dev/null +++ b/Spigot-Server-Patches/0312-PlayerReadyArrowEvent.patch @@ -0,0 +1,79 @@ +From 28ac9602f72e89716a8862ab3cd5f6438a0dc000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 18 Jun 2018 01:12:53 -0400 +Subject: [PATCH] PlayerReadyArrowEvent + +Called when a player is firing a bow and the server is choosing an arrow to use. +Plugins can skip selection of certain arrows and control which is used. + +diff --git a/src/main/java/net/minecraft/server/ItemBow.java b/src/main/java/net/minecraft/server/ItemBow.java +index 327d31e19..44e7be58e 100644 +--- a/src/main/java/net/minecraft/server/ItemBow.java ++++ b/src/main/java/net/minecraft/server/ItemBow.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.event.entity.EntityCombustEvent; // CraftBukkit + + public class ItemBow extends Item { +@@ -14,16 +15,16 @@ public class ItemBow extends Item { + }); + } + +- private ItemStack a(EntityHuman entityhuman) { +- if (this.d(entityhuman.b(EnumHand.OFF_HAND))) { ++ private ItemStack a(EntityHuman entityhuman, ItemStack bow) { // Paper ++ if (this.d(entityhuman, bow, entityhuman.b(EnumHand.OFF_HAND))) { // Paper + return entityhuman.b(EnumHand.OFF_HAND); +- } else if (this.d(entityhuman.b(EnumHand.MAIN_HAND))) { ++ } else if (this.d(entityhuman, bow, entityhuman.b(EnumHand.MAIN_HAND))) { // Paper + return entityhuman.b(EnumHand.MAIN_HAND); + } else { + for (int i = 0; i < entityhuman.inventory.getSize(); ++i) { + ItemStack itemstack = entityhuman.inventory.getItem(i); + +- if (this.d(itemstack)) { ++ if (this.d(entityhuman, bow, itemstack)) { // Paper + return itemstack; + } + } +@@ -32,15 +33,23 @@ public class ItemBow extends Item { + } + } + +- protected boolean d(ItemStack itemstack) { +- return itemstack.getItem() instanceof ItemArrow; ++ // Paper start ++ protected boolean d(EntityHuman player, ItemStack bow, ItemStack itemstack) { ++ return itemstack.getItem() instanceof ItemArrow && ( ++ !(player instanceof EntityPlayer) || ++ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( ++ ((EntityPlayer) player).getBukkitEntity(), ++ CraftItemStack.asCraftMirror(bow), ++ CraftItemStack.asCraftMirror(itemstack) ++ ).callEvent()); ++ // Paper end + } + + public void a(ItemStack itemstack, World world, EntityLiving entityliving, int i) { + if (entityliving instanceof EntityHuman) { + EntityHuman entityhuman = (EntityHuman) entityliving; + boolean flag = entityhuman.abilities.canInstantlyBuild || EnchantmentManager.getEnchantmentLevel(Enchantments.ARROW_INFINITE, itemstack) > 0; +- ItemStack itemstack1 = this.a(entityhuman); ++ ItemStack itemstack1 = this.a(entityhuman, itemstack); // Paper + + if (!itemstack1.isEmpty() || flag) { + if (itemstack1.isEmpty()) { +@@ -144,7 +153,7 @@ public class ItemBow extends Item { + + public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { + ItemStack itemstack = entityhuman.b(enumhand); +- boolean flag = !this.a(entityhuman).isEmpty(); ++ boolean flag = !this.a(entityhuman, itemstack).isEmpty(); // Paper + + if (!entityhuman.abilities.canInstantlyBuild && !flag) { + return flag ? new InteractionResultWrapper(EnumInteractionResult.PASS, itemstack) : new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); +-- +2.17.1 +