aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0214-PlayerLaunchProjectileEvent.patch
blob: be34c111d31a269407d329f3074d64c6b8cca9a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <Blake.Galbreath@GMail.com>
Date: Sat, 21 Jul 2018 03:11:03 -0500
Subject: [PATCH] PlayerLaunchProjectileEvent


diff --git a/src/main/java/net/minecraft/world/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java
index be7d1bfb13cf0afb80ba98f3b56602bccebeab64..4ebd634cff286b10868e26eeb3ecf34abdcab22e 100644
--- a/src/main/java/net/minecraft/world/item/EggItem.java
+++ b/src/main/java/net/minecraft/world/item/EggItem.java
@@ -28,19 +28,31 @@ public class EggItem extends Item implements ProjectileItem {
 
             entityegg.setItem(itemstack);
             entityegg.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F);
-            // CraftBukkit start
-            if (!world.addFreshEntity(entityegg)) {
+            // Paper start - PlayerLaunchProjectileEvent
+            com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity());
+            if (event.callEvent() && world.addFreshEntity(entityegg)) {
+                if (event.shouldConsume()) {
+                    itemstack.consume(1, user);
+                } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+                }
+
+                world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), net.minecraft.sounds.SoundEvents.EGG_THROW, net.minecraft.sounds.SoundSource.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F));
+                user.awardStat(Stats.ITEM_USED.get(this));
+            } else {
                 if (user instanceof net.minecraft.server.level.ServerPlayer) {
                     ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
                 }
                 return InteractionResultHolder.fail(itemstack);
             }
-            // CraftBukkit end
+            // Paper end - PlayerLaunchProjectileEvent
         }
         world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
 
+        /* // Paper start - PlayerLaunchProjectileEvent; moved up
         user.awardStat(Stats.ITEM_USED.get(this));
         itemstack.consume(1, user);
+        */ // Paper end - PlayerLaunchProjectileEvent
         return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide());
     }
 
diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java
index 48048204b619dd515253c8ffb05a0f7105ef7718..20a91d798d31a71b3c05efa2cc5bda55494e26cc 100644
--- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java
+++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java
@@ -25,7 +25,20 @@ public class EnderpearlItem extends Item {
 
             entityenderpearl.setItem(itemstack);
             entityenderpearl.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F);
-            if (!world.addFreshEntity(entityenderpearl)) {
+            // Paper start - PlayerLaunchProjectileEvent
+            com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity());
+            if (event.callEvent() && world.addFreshEntity(entityenderpearl)) {
+                if (event.shouldConsume()) {
+                    itemstack.consume(1, user);
+                } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+                }
+
+                world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F));
+                user.awardStat(Stats.ITEM_USED.get(this));
+                user.getCooldowns().addCooldown(this, 20);
+            } else {
+                // Paper end - PlayerLaunchProjectileEvent
                 if (user instanceof net.minecraft.server.level.ServerPlayer) {
                     ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
                 }
@@ -33,12 +46,14 @@ public class EnderpearlItem extends Item {
             }
         }
 
+        /* // Paper start - PlayerLaunchProjectileEvent; moved up
         world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
         user.getCooldowns().addCooldown(this, 20);
         // CraftBukkit end
 
         user.awardStat(Stats.ITEM_USED.get(this));
         itemstack.consume(1, user);
+        */ // Paper end - PlayerLaunchProjectileEvent; moved up
         return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide());
     }
 }
diff --git a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java
index 686f0fd87e06fa7552d66fd3e38a3e059c22f180..7448309b6dca619b6366aa55fe3a395a830ffbdd 100644
--- a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java
+++ b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java
@@ -20,25 +20,44 @@ public class ExperienceBottleItem extends Item implements ProjectileItem {
     @Override
     public InteractionResultHolder<ItemStack> use(Level world, Player user, InteractionHand hand) {
         ItemStack itemStack = user.getItemInHand(hand);
-        world.playSound(
-            null,
-            user.getX(),
-            user.getY(),
-            user.getZ(),
-            SoundEvents.EXPERIENCE_BOTTLE_THROW,
-            SoundSource.NEUTRAL,
-            0.5F,
-            0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
-        );
+        // Paper - PlayerLaunchProjectileEvent; moved down
         if (!world.isClientSide) {
             ThrownExperienceBottle thrownExperienceBottle = new ThrownExperienceBottle(world, user);
             thrownExperienceBottle.setItem(itemStack);
             thrownExperienceBottle.shootFromRotation(user, user.getXRot(), user.getYRot(), -20.0F, 0.7F, 1.0F);
-            world.addFreshEntity(thrownExperienceBottle);
+            // Paper start - PlayerLaunchProjectileEvent
+            com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownExperienceBottle.getBukkitEntity());
+            if (event.callEvent() && world.addFreshEntity(thrownExperienceBottle)) {
+                if (event.shouldConsume()) {
+                    itemStack.consume(1, user);
+                } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+                }
+
+                world.playSound(
+                    null,
+                    user.getX(),
+                    user.getY(),
+                    user.getZ(),
+                    SoundEvents.EXPERIENCE_BOTTLE_THROW,
+                    SoundSource.NEUTRAL,
+                    0.5F,
+                    0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
+                );
+                user.awardStat(Stats.ITEM_USED.get(this));
+            } else {
+                if (user instanceof net.minecraft.server.level.ServerPlayer) {
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+                }
+                return InteractionResultHolder.fail(itemStack);
+            }
+            // Paper end - PlayerLaunchProjectileEvent
         }
 
+        /* // Paper start - PlayerLaunchProjectileEvent; moved up
         user.awardStat(Stats.ITEM_USED.get(this));
         itemStack.consume(1, user);
+        */ // Paper end - PlayerLaunchProjectileEvent
         return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide());
     }
 
diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
index 16da60b7ecf2e0d4a49804dfa1ad47d4ae672571..218f2f085309f04438f8b07bc41cf242583db2dc 100644
--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
@@ -43,8 +43,12 @@ public class FireworkRocketItem extends Item implements ProjectileItem {
                 itemStack
             );
             fireworkRocketEntity.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID(); // Paper
-            level.addFreshEntity(fireworkRocketEntity);
-            itemStack.shrink(1);
+            // Paper start - PlayerLaunchProjectileEvent
+            com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) fireworkRocketEntity.getBukkitEntity());
+            if (!event.callEvent() || !level.addFreshEntity(fireworkRocketEntity)) return InteractionResult.PASS;
+            if (event.shouldConsume() && !context.getPlayer().getAbilities().instabuild) itemStack.shrink(1);
+            else if (context.getPlayer() instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory();
+            // Paper end - PlayerLaunchProjectileEvent
         }
 
         return InteractionResult.sidedSuccess(level.isClientSide);
diff --git a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java
index b94888d359ec92bf7ef77b0610f41ba75185a26e..c9b511cc4f2499ca13e3cd8f1cdabdc225f66b9c 100644
--- a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java
+++ b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java
@@ -24,6 +24,10 @@ public class LingeringPotionItem extends ThrowablePotionItem {
 
     @Override
     public InteractionResultHolder<ItemStack> use(Level world, Player user, InteractionHand hand) {
+        // Paper start - PlayerLaunchProjectileEvent
+        InteractionResultHolder<ItemStack> wrapper = super.use(world, user, hand);
+        if (wrapper.getResult() != net.minecraft.world.InteractionResult.FAIL) {
+        // Paper end - PlayerLaunchProjectileEvent
         world.playSound(
             null,
             user.getX(),
@@ -34,6 +38,9 @@ public class LingeringPotionItem extends ThrowablePotionItem {
             0.5F,
             0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
         );
-        return super.use(world, user, hand);
+        // Paper start - PlayerLaunchProjectileEvent
+        }
+        return wrapper;
+        // Paper end - PlayerLaunchProjectileEvent
     }
 }
diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java
index 2ae40936b31012fab0c7c42a7dea13b01ec6068f..32b170551a2f5bdc88d29f4d03750bfe3974e71b 100644
--- a/src/main/java/net/minecraft/world/item/SnowballItem.java
+++ b/src/main/java/net/minecraft/world/item/SnowballItem.java
@@ -29,17 +29,26 @@ public class SnowballItem extends Item implements ProjectileItem {
 
             entitysnowball.setItem(itemstack);
             entitysnowball.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F);
-            if (world.addFreshEntity(entitysnowball)) {
-                itemstack.consume(1, user);
+            // Paper start - PlayerLaunchProjectileEvent
+            com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity());
+            if (event.callEvent() && world.addFreshEntity(entitysnowball)) {
+                user.awardStat(Stats.ITEM_USED.get(this));
+                if (event.shouldConsume()) {
+                    // Paper end - PlayerLaunchProjectileEvent
+                    itemstack.consume(1, user);
+                } else if (user instanceof net.minecraft.server.level.ServerPlayer) {  // Paper - PlayerLaunchProjectileEvent
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();  // Paper - PlayerLaunchProjectileEvent
+                }
 
                 world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
-            } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
-                ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+            } else { // Paper - PlayerLaunchProjectileEvent
+                if (user instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper - PlayerLaunchProjectileEvent
+                return InteractionResultHolder.fail(itemstack); // Paper - PlayerLaunchProjectileEvent
             }
         }
         // CraftBukkit end
 
-        user.awardStat(Stats.ITEM_USED.get(this));
+        // user.awardStat(Stats.ITEM_USED.get(this)); // Paper - PlayerLaunchProjectileEvent; moved up
         // itemstack.consume(1, entityhuman); // CraftBukkit - moved up
         return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide());
     }
diff --git a/src/main/java/net/minecraft/world/item/SplashPotionItem.java b/src/main/java/net/minecraft/world/item/SplashPotionItem.java
index 935c34ba7eb14348becdd3ac0c29766abf7ca614..73bac60b3bf6d20d415a8250d0426251c0c3265b 100644
--- a/src/main/java/net/minecraft/world/item/SplashPotionItem.java
+++ b/src/main/java/net/minecraft/world/item/SplashPotionItem.java
@@ -14,6 +14,10 @@ public class SplashPotionItem extends ThrowablePotionItem {
 
     @Override
     public InteractionResultHolder<ItemStack> use(Level world, Player user, InteractionHand hand) {
+        // Paper start - PlayerLaunchProjectileEvent
+        InteractionResultHolder<ItemStack> wrapper = super.use(world, user, hand);
+        if (wrapper.getResult() != net.minecraft.world.InteractionResult.FAIL) {
+        // Paper end - PlayerLaunchProjectileEvent
         world.playSound(
             null,
             user.getX(),
@@ -24,6 +28,9 @@ public class SplashPotionItem extends ThrowablePotionItem {
             0.5F,
             0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
         );
-        return super.use(world, user, hand);
+        // Paper start - PlayerLaunchProjectileEvent
+        }
+        return wrapper;
+        // Paper end - PlayerLaunchProjectileEvent
     }
 }
diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java
index 12795451393e48f5c9ab4b1dfd9369e1ee6e0367..369955746f4b51f69fa01103e3771dd74fc6c8f0 100644
--- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java
+++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java
@@ -22,11 +22,29 @@ public class ThrowablePotionItem extends PotionItem implements ProjectileItem {
             ThrownPotion thrownPotion = new ThrownPotion(world, user);
             thrownPotion.setItem(itemStack);
             thrownPotion.shootFromRotation(user, user.getXRot(), user.getYRot(), -20.0F, 0.5F, 1.0F);
-            world.addFreshEntity(thrownPotion);
+            // Paper start - PlayerLaunchProjectileEvent
+            com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownPotion.getBukkitEntity());
+            if (event.callEvent() && world.addFreshEntity(thrownPotion)) {
+                if (event.shouldConsume()) {
+                    itemStack.consume(1, user);
+                } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+                }
+
+                user.awardStat(Stats.ITEM_USED.get(this));
+            } else {
+                if (user instanceof net.minecraft.server.level.ServerPlayer) {
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+                }
+                return InteractionResultHolder.fail(itemStack);
+            }
+            // Paper end - PlayerLaunchProjectileEvent
         }
 
+        /* // Paper start - PlayerLaunchProjectileEvent; moved up
         user.awardStat(Stats.ITEM_USED.get(this));
         itemStack.consume(1, user);
+        */ // Paper end
         return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide());
     }
 
diff --git a/src/main/java/net/minecraft/world/item/TridentItem.java b/src/main/java/net/minecraft/world/item/TridentItem.java
index 2d34f206b4b02d5f2ee35101233afc6b4f58a579..f1b2d388a1a40a1d909a2e726f32d6c15e1eb0eb 100644
--- a/src/main/java/net/minecraft/world/item/TridentItem.java
+++ b/src/main/java/net/minecraft/world/item/TridentItem.java
@@ -87,19 +87,24 @@ public class TridentItem extends Item implements ProjectileItem {
                                 }
 
                                 // CraftBukkit start
-                                if (!world.addFreshEntity(entitythrowntrident)) {
+                                // Paper start - PlayerLaunchProjectileEvent
+                                com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), (org.bukkit.entity.Projectile) entitythrowntrident.getBukkitEntity());
+                                if (!event.callEvent() || !world.addFreshEntity(entitythrowntrident)) {
+                                    // Paper end - PlayerLaunchProjectileEvent
                                     if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) {
                                         ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory();
                                     }
                                     return;
                                 }
 
+                                if (event.shouldConsume()) { // Paper - PlayerLaunchProjectileEvent
                                 stack.hurtAndBreak(1, entityhuman, LivingEntity.getSlotForHand(user.getUsedItemHand()));
+                                } // Paper - PlayerLaunchProjectileEvent
                                 entitythrowntrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved
                                 // CraftBukkit end
 
                                 world.playSound((Player) null, (Entity) entitythrowntrident, (SoundEvent) holder.value(), SoundSource.PLAYERS, 1.0F, 1.0F);
-                                if (!entityhuman.hasInfiniteMaterials()) {
+                                if (event.shouldConsume() && !entityhuman.hasInfiniteMaterials()) { // Paper - PlayerLaunchProjectileEvent
                                     entityhuman.getInventory().removeItem(stack);
                                 }
                                 // CraftBukkit start - SPIGOT-5458 also need in this branch :(
diff --git a/src/main/java/net/minecraft/world/item/WindChargeItem.java b/src/main/java/net/minecraft/world/item/WindChargeItem.java
index 6222e867bb959fab05bcd8f2114ab00b26847c3e..eed0d754e9a3c7c94614e0fd54651500e0612ea8 100644
--- a/src/main/java/net/minecraft/world/item/WindChargeItem.java
+++ b/src/main/java/net/minecraft/world/item/WindChargeItem.java
@@ -24,10 +24,26 @@ public class WindChargeItem extends Item implements ProjectileItem {
 
     @Override
     public InteractionResultHolder<ItemStack> use(Level world, Player user, InteractionHand hand) {
+        ItemStack itemStack = user.getItemInHand(hand); // Paper - PlayerLaunchProjectileEvent; moved from below
+        boolean shouldConsume = true; // Paper - PlayerLaunchProjectileEvent
         if (!world.isClientSide()) {
             WindCharge windCharge = new WindCharge(user, world, user.position().x(), user.getEyePosition().y(), user.position().z());
             windCharge.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F);
-            world.addFreshEntity(windCharge);
+            // Paper start - PlayerLaunchProjectileEvent
+            com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) windCharge.getBukkitEntity());
+            if (!event.callEvent() || !world.addFreshEntity(windCharge)) {
+                user.containerMenu.sendAllDataToRemote();
+                if (user instanceof net.minecraft.server.level.ServerPlayer player) {
+                    player.connection.send(new net.minecraft.network.protocol.game.ClientboundCooldownPacket(this, 0)); // prevent visual desync of cooldown on the slot
+                }
+                return InteractionResultHolder.fail(itemStack);
+            }
+
+            shouldConsume = event.shouldConsume();
+            if (!shouldConsume && !user.hasInfiniteMaterials()) {
+                user.containerMenu.sendAllDataToRemote();
+            }
+            // Paper end - PlayerLaunchProjectileEvent
         }
 
         world.playSound(
@@ -40,10 +56,9 @@ public class WindChargeItem extends Item implements ProjectileItem {
             0.5F,
             0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
         );
-        ItemStack itemStack = user.getItemInHand(hand);
         user.getCooldowns().addCooldown(this, 10);
         user.awardStat(Stats.ITEM_USED.get(this));
-        itemStack.consume(1, user);
+        if (shouldConsume) itemStack.consume(1, user); // Paper - PlayerLaunchProjectileEvent
         return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide());
     }