Skip to content

Commit

Permalink
Revamp crossbow load event
Browse files Browse the repository at this point in the history
  • Loading branch information
lynxplay committed Oct 2, 2024
1 parent 209ec88 commit 1ec5810
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
Expand All @@ -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;
}
62 changes: 54 additions & 8 deletions patches/server/0200-Improve-EntityShootBowEvent.patch
Original file line number Diff line number Diff line change
Expand Up @@ -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<ItemStack> list = draw(stack, itemStack, player);
- List<ItemStack> list = draw(stack, itemStack, player);
+ List<ItemStack> 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
Expand All @@ -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 {
Expand All @@ -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());
Expand Down Expand Up @@ -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<ItemStack> 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<ItemStack> 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;

42 changes: 20 additions & 22 deletions patches/server/0459-Add-EntityLoadCrossbowEvent.patch
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -36,33 +36,31 @@ index 6e38d4592dcff69e52fbd0f3bae75da9619fd550..68f1e837dfef9954fa47d7d6523c6e48
+ return CrossbowItem.tryLoadProjectiles(shooter, crossbow, true);
+ }
+ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow, boolean consume) {
+ List<ItemStack> list = draw(crossbow, shooter.getProjectile(crossbow), shooter, consume);
+ List<ItemStack> 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<ItemStack> 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<ItemStack> draw(ItemStack stack, ItemStack projectileStack, LivingEntity shooter) {
+ // Paper start
+ return draw(stack, projectileStack, shooter, true);
+ }
+ protected static List<ItemStack> 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) {

0 comments on commit 1ec5810

Please sign in to comment.