From 1ec581040c01812cf34888a578995e6c71044f19 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Wed, 2 Oct 2024 14:26:52 +0200 Subject: [PATCH] Revamp crossbow load event --- ...ent-consumeArrow-and-getArrowItem-AP.patch | 16 ++++- .../0200-Improve-EntityShootBowEvent.patch | 62 ++++++++++++++++--- .../0459-Add-EntityLoadCrossbowEvent.patch | 42 ++++++------- 3 files changed, 87 insertions(+), 33 deletions(-) diff --git a/patches/api/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/patches/api/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch index 21f357efafdf..c9cde5b0debf 100644 --- a/patches/api/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch +++ b/patches/api/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch @@ -6,7 +6,7 @@ Subject: [PATCH] EntityShootBowEvent consumeArrow and getArrowItem API Adds ability to get what arrow was shot, and control if it should be consumed. diff --git a/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java b/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java -index 1a8366f6757431baaba4f3d48abea3cf0ec1f1ad..e4efcd757ca51a4edd396f55c812dbe89ffb68c7 100644 +index 1a8366f6757431baaba4f3d48abea3cf0ec1f1ad..1da003ded82f943eff0438126227d1d84599f681 100644 --- a/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java @@ -22,7 +22,32 @@ public class EntityShootBowEvent extends EntityEvent implements Cancellable { @@ -28,12 +28,12 @@ index 1a8366f6757431baaba4f3d48abea3cf0ec1f1ad..e4efcd757ca51a4edd396f55c812dbe8 + public ItemStack getArrowItem() { + return this.getConsumable(); + } -+ + + @Deprecated + public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @NotNull final Entity projectile, final float force) { + this(shooter, bow, new ItemStack(org.bukkit.Material.AIR), projectile, force); + } - ++ + @Deprecated + public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @NotNull ItemStack arrowItem, @NotNull final Entity projectile, final float force) { + this(shooter, bow, arrowItem, projectile, EquipmentSlot.HAND, force, true); @@ -42,3 +42,13 @@ index 1a8366f6757431baaba4f3d48abea3cf0ec1f1ad..e4efcd757ca51a4edd396f55c812dbe8 public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @Nullable final ItemStack consumable, @NotNull final Entity projectile, @NotNull final EquipmentSlot hand, final float force, final boolean consumeItem) { super(shooter); this.bow = bow; +@@ -112,9 +137,7 @@ public class EntityShootBowEvent extends EntityEvent implements Cancellable { + * consumed). + * + * @param consumeItem whether or not to consume the item +- * @deprecated not currently functional + */ +- @Deprecated + public void setConsumeItem(boolean consumeItem) { + this.consumeItem = consumeItem; + } diff --git a/patches/server/0200-Improve-EntityShootBowEvent.patch b/patches/server/0200-Improve-EntityShootBowEvent.patch index 10bedeb17d53..bce9c7a00a2b 100644 --- a/patches/server/0200-Improve-EntityShootBowEvent.patch +++ b/patches/server/0200-Improve-EntityShootBowEvent.patch @@ -46,12 +46,15 @@ index 93e3454de0b0d62895f165b0772526f3eae1e333..c858556ea457931aa14e338e20672cb5 @Override diff --git a/src/main/java/net/minecraft/world/item/BowItem.java b/src/main/java/net/minecraft/world/item/BowItem.java -index 6eb5c0f23d9dc61e69ad5ad493c89602a9dcd4b5..ac5056efcbfc251f12b016c4e51c98ee77418db1 100644 +index 6eb5c0f23d9dc61e69ad5ad493c89602a9dcd4b5..795489936265bd5f52afdca3122479ffbf8cfe80 100644 --- a/src/main/java/net/minecraft/world/item/BowItem.java +++ b/src/main/java/net/minecraft/world/item/BowItem.java -@@ -32,7 +32,7 @@ public class BowItem extends ProjectileWeaponItem { +@@ -30,9 +30,9 @@ public class BowItem extends ProjectileWeaponItem { + int i = this.getUseDuration(stack, user) - remainingUseTicks; + float f = getPowerForTime(i); if (!((double)f < 0.1)) { - List list = draw(stack, itemStack, player); +- List list = draw(stack, itemStack, player); ++ List list = draw(stack, itemStack, player, ProjectileDrawingItemConsumption.MAYBE_LATER); // // Paper - improve shoot bow - correctly prevent item consumption if (world instanceof ServerLevel serverLevel && !list.isEmpty()) { - this.shoot(serverLevel, player, player.getUsedItemHand(), stack, list, f * 3.0F, 1.0F, f == 1.0F, null); + if (!this.shoot(serverLevel, player, player.getUsedItemHand(), stack, new UnrealizedDrawResult(list, itemStack), f * 3.0F, 1.0F, f == 1.0F, null)) return; // Paper - improve shoot bow - correctly prevent item consumption / return if all events were cancelled @@ -72,7 +75,7 @@ index ac983b6f0bd3d3294481d08831063b6e232e5ef6..6e38d4592dcff69e52fbd0f3bae75da9 CriteriaTriggers.SHOT_CROSSBOW.trigger(serverPlayer, stack); serverPlayer.awardStat(Stats.ITEM_USED.get(stack.getItem())); diff --git a/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java b/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java -index 56595dd3a0b7df4b5f9819ade797212278c8fd40..6952acb1e1cbe6eb1a1811a6ce1a3b630347454e 100644 +index 56595dd3a0b7df4b5f9819ade797212278c8fd40..8154773fd74d76e83a65e518e6f6959f1012033c 100644 --- a/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java +++ b/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java @@ -46,7 +46,35 @@ public abstract class ProjectileWeaponItem extends Item { @@ -91,8 +94,8 @@ index 56595dd3a0b7df4b5f9819ade797212278c8fd40..6952acb1e1cbe6eb1a1811a6ce1a3b63 + final ItemStack nonIntangibleStack = projectileStacks.get(projectStackIndex); + + // The stack at index 0 was intangible, this means that net.minecraft.world.item.ProjectileWeaponItem.useAmmo -+ // determined the player was not consuming items anyway, e.g. via creative mode. Do not remove items in this -+ // case. ++ // determined the player was not consuming items anyway, e.g. via creative mode or because of other API means. ++ // Do not remove items in this case. + if (nonIntangibleStack.has(DataComponents.INTANGIBLE_PROJECTILE)) return; + + originalInPlayerInventory.shrink(nonIntangibleStack.getCount()); @@ -142,12 +145,55 @@ index 56595dd3a0b7df4b5f9819ade797212278c8fd40..6952acb1e1cbe6eb1a1811a6ce1a3b63 } protected int getDurabilityUse(ItemStack projectile) { -@@ -174,7 +206,7 @@ public abstract class ProjectileWeaponItem extends Item { +@@ -114,6 +146,21 @@ public abstract class ProjectileWeaponItem extends Item { + } + + protected static List draw(ItemStack stack, ItemStack projectileStack, LivingEntity shooter) { ++ // Paper start - improve bow shoot event - delayed consumption to allow for consumption cancellation ++ return draw(stack, projectileStack, shooter); ++ } ++ protected enum ProjectileDrawingItemConsumption { ++ // Will immediately consume from the passed projectile stack, like vanilla would ++ IMMEDIATELY, ++ ++ // Will create a copyWithCount from the projectileStack, allowing for later reduction. ++ // The stacks yielded will adhere to vanilla's intangibility layout, with the first itemstack ++ // being tangible, allowing for it to be picked up once shot. ++ // Callers that do *not* consume later are responsible for marking the shot projectile as intangible. ++ MAYBE_LATER, ++ } ++ protected static List draw(ItemStack stack, ItemStack projectileStack, LivingEntity shooter, final ProjectileDrawingItemConsumption consumption) { ++ // Paper end - improve bow shoot event - delayed consumption to allow for consumption cancellation + if (projectileStack.isEmpty()) { + return List.of(); + } else { +@@ -133,7 +180,7 @@ public abstract class ProjectileWeaponItem extends Item { + ItemStack itemstack2 = projectileStack.copy(); + + for (int k = 0; k < j; ++k) { +- ItemStack itemstack3 = ProjectileWeaponItem.useAmmo(stack, k == 0 ? projectileStack : itemstack2, shooter, k > 0); ++ ItemStack itemstack3 = ProjectileWeaponItem.useAmmo(stack, k == 0 ? projectileStack : itemstack2, shooter, k > 0, consumption); + + if (!itemstack3.isEmpty()) { + list.add(itemstack3); +@@ -145,6 +192,11 @@ public abstract class ProjectileWeaponItem extends Item { + } + + protected static ItemStack useAmmo(ItemStack stack, ItemStack projectileStack, LivingEntity shooter, boolean multishot) { ++ // Paper start - improve bow shoot event - delayed consumption to allow for consumption cancellation ++ return useAmmo(stack, projectileStack, shooter, multishot, ProjectileDrawingItemConsumption.IMMEDIATELY); ++ } ++ protected static ItemStack useAmmo(ItemStack stack, ItemStack projectileStack, LivingEntity shooter, boolean multishot, final ProjectileDrawingItemConsumption consumption) { ++ // Paper end - improve bow shoot event - delayed consumption to allow for consumption cancellation + int i; + label28: + { +@@ -174,7 +226,7 @@ public abstract class ProjectileWeaponItem extends Item { itemstack2.set(DataComponents.INTANGIBLE_PROJECTILE, Unit.INSTANCE); return itemstack2; } else { - itemstack2 = projectileStack.split(j); -+ itemstack2 = projectileStack.copyWithCount(j); // Paper - improve bow shoot event - do not reduce item in player inventory just yet - create full copy ++ itemstack2 = consumption == ProjectileDrawingItemConsumption.MAYBE_LATER ? projectileStack.copyWithCount(j) : projectileStack.split(j); // Paper - improve bow shoot event - do not reduce item in player inventory just yet - create full copy if configured if (projectileStack.isEmpty() && shooter instanceof Player) { Player entityhuman = (Player) shooter; diff --git a/patches/server/0459-Add-EntityLoadCrossbowEvent.patch b/patches/server/0459-Add-EntityLoadCrossbowEvent.patch index 30666d91ddb6..07ff7cf97842 100644 --- a/patches/server/0459-Add-EntityLoadCrossbowEvent.patch +++ b/patches/server/0459-Add-EntityLoadCrossbowEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add EntityLoadCrossbowEvent diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java -index 6e38d4592dcff69e52fbd0f3bae75da9619fd550..68f1e837dfef9954fa47d7d6523c6e482dafb5ea 100644 +index 6e38d4592dcff69e52fbd0f3bae75da9619fd550..6ba8b38425291cf2469dad8016dbae5a2bbdb751 100644 --- a/src/main/java/net/minecraft/world/item/CrossbowItem.java +++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java @@ -89,7 +89,14 @@ public class CrossbowItem extends ProjectileWeaponItem { @@ -36,33 +36,31 @@ index 6e38d4592dcff69e52fbd0f3bae75da9619fd550..68f1e837dfef9954fa47d7d6523c6e48 + return CrossbowItem.tryLoadProjectiles(shooter, crossbow, true); + } + private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow, boolean consume) { -+ List list = draw(crossbow, shooter.getProjectile(crossbow), shooter, consume); ++ List list = draw(crossbow, shooter.getProjectile(crossbow), shooter, consume ? ProjectileDrawingItemConsumption.IMMEDIATELY : ProjectileDrawingItemConsumption.NEVER); + // Paper end - Add EntityLoadCrossbowEvent if (!list.isEmpty()) { crossbow.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.of(list)); return true; diff --git a/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java b/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java -index 193d74236a895b716b86962be405bb3cf44cd4a8..312c8d3da59750440cebc2c574cb2615cbdb0727 100644 +index 8154773fd74d76e83a65e518e6f6959f1012033c..52555846a873f5006c58f7e1e08f5190854c30ba 100644 --- a/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java +++ b/src/main/java/net/minecraft/world/item/ProjectileWeaponItem.java -@@ -146,6 +146,11 @@ public abstract class ProjectileWeaponItem extends Item { +@@ -158,6 +158,9 @@ public abstract class ProjectileWeaponItem extends Item { + // being tangible, allowing for it to be picked up once shot. + // Callers that do *not* consume later are responsible for marking the shot projectile as intangible. + MAYBE_LATER, ++ ++ // Will not reduce the passed projectile stack and prepare all returned items to be intangible. ++ NEVER, } + protected static List draw(ItemStack stack, ItemStack projectileStack, LivingEntity shooter, final ProjectileDrawingItemConsumption consumption) { + // Paper end - improve bow shoot event - delayed consumption to allow for consumption cancellation +@@ -200,7 +203,7 @@ public abstract class ProjectileWeaponItem extends Item { + int i; + label28: + { +- if (!multishot && !shooter.hasInfiniteMaterials()) { ++ if (!multishot && !shooter.hasInfiniteMaterials() && consumption != ProjectileDrawingItemConsumption.NEVER) { // Paper - add EntityLoadCrossbowEvent + Level world = shooter.level(); - protected static List draw(ItemStack stack, ItemStack projectileStack, LivingEntity shooter) { -+ // Paper start -+ return draw(stack, projectileStack, shooter, true); -+ } -+ protected static List draw(ItemStack stack, ItemStack projectileStack, LivingEntity shooter, boolean consume) { -+ // Paper end - if (projectileStack.isEmpty()) { - return List.of(); - } else { -@@ -165,7 +170,7 @@ public abstract class ProjectileWeaponItem extends Item { - ItemStack itemstack2 = projectileStack.copy(); - - for (int k = 0; k < j; ++k) { -- ItemStack itemstack3 = ProjectileWeaponItem.useAmmo(stack, k == 0 ? projectileStack : itemstack2, shooter, k > 0); -+ ItemStack itemstack3 = ProjectileWeaponItem.useAmmo(stack, k == 0 ? projectileStack : itemstack2, shooter, k > 0 || !consume); // Paper - - if (!itemstack3.isEmpty()) { - list.add(itemstack3); + if (world instanceof ServerLevel) {