aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0212-PlayerLaunchProjectileEvent.patch
blob: b41463a06a1537bc676ef523cf1f1c8ad415a8dd (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
364
365
366
367
368
369
370
371
372
373
374
375
376
377
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/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
index f8ae12a3540c4a7aa7e2c1656cbd866e33e11f57..d6dfda0580d919eb8a000113e7f9dd9794117b45 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
@@ -197,7 +197,12 @@ public abstract class Projectile extends Entity implements TraceableEntity {
     }
 
     public static <T extends Projectile> T spawnProjectileFromRotation(Projectile.ProjectileFactory<T> creator, ServerLevel world, ItemStack projectileStack, LivingEntity shooter, float roll, float power, float divergence) {
-        return Projectile.spawnProjectile(creator.create(world, shooter, projectileStack), world, projectileStack, (iprojectile) -> {
+    // Paper start - PlayerLaunchProjectileEvent
+        return spawnProjectileFromRotationDelayed(creator, world, projectileStack, shooter, roll, power, divergence).spawn();
+    }
+    public static <T extends Projectile> Delayed<T> spawnProjectileFromRotationDelayed(Projectile.ProjectileFactory<T> creator, ServerLevel world, ItemStack projectileStack, LivingEntity shooter, float roll, float power, float divergence) {
+        return Projectile.spawnProjectileDelayed(creator.create(world, shooter, projectileStack), world, projectileStack, (iprojectile) -> {
+    // Paper end - PlayerLaunchProjectileEvent
             iprojectile.shootFromRotation(shooter, shooter.getXRot(), shooter.getYRot(), roll, power, divergence);
         });
     }
diff --git a/src/main/java/net/minecraft/world/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java
index 8ddc1fa76244265616309322170c3a1b821c5092..3ddd34e5d05fa1355a2affd329d72dea216cd0e4 100644
--- a/src/main/java/net/minecraft/world/item/EggItem.java
+++ b/src/main/java/net/minecraft/world/item/EggItem.java
@@ -26,7 +26,19 @@ public class EggItem extends Item implements ProjectileItem {
         // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - moved down
         if (world instanceof ServerLevel worldserver) {
             // CraftBukkit start
-            if (Projectile.spawnProjectileFromRotation(ThrownEgg::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F).isRemoved()) {
+            // Paper start - PlayerLaunchProjectileEvent
+            final Projectile.Delayed<ThrownEgg> thrownEgg = Projectile.spawnProjectileFromRotationDelayed(ThrownEgg::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F);
+            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) thrownEgg.projectile().getBukkitEntity());
+            if (event.callEvent() && thrownEgg.attemptSpawn()) {
+                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.EGG_THROW, SoundSource.PLAYERS, 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();
                 }
@@ -35,9 +47,7 @@ public class EggItem extends Item implements ProjectileItem {
             // CraftBukkit end
         }
         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));
-
-        user.awardStat(Stats.ITEM_USED.get(this));
-        itemstack.consume(1, user);
+        // Paper - PlayerLaunchProjectileEvent - moved up
         return InteractionResult.SUCCESS;
     }
 
diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java
index b9e24451a8f87479377e3324b3a956c0efc3e53c..b232390d8ee8e449e61c0ea7f3af60df507abb97 100644
--- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java
+++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java
@@ -23,7 +23,20 @@ public class EnderpearlItem extends Item {
 
         if (world instanceof ServerLevel worldserver) {
             // CraftBukkit start
-            if (Projectile.spawnProjectileFromRotation(ThrownEnderpearl::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F).isRemoved()) {
+            // Paper start - PlayerLaunchProjectileEvent
+            final Projectile.Delayed<ThrownEnderpearl> thrownEnderpearl = Projectile.spawnProjectileFromRotationDelayed(ThrownEnderpearl::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F);
+            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) thrownEnderpearl.projectile().getBukkitEntity());
+            if (event.callEvent() && thrownEnderpearl.attemptSpawn()) {
+                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 / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+                user.awardStat(Stats.ITEM_USED.get(this));
+            } else {
+            // Paper end - PlayerLaunchProjectileEvent
                 if (user instanceof net.minecraft.server.level.ServerPlayer) {
                     ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
                 }
@@ -33,8 +46,7 @@ public class EnderpearlItem extends Item {
         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));
         // CraftBukkit end
 
-        user.awardStat(Stats.ITEM_USED.get(this));
-        itemstack.consume(1, user);
+        // Paper - PlayerLaunchProjectileEvent - moved up
         return InteractionResult.SUCCESS;
     }
 }
diff --git a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java
index b255e40277585928a767e5efd4b61708e13dab50..dfa3f9534159400e539ee61debedffb5f978aae8 100644
--- a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java
+++ b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java
@@ -21,22 +21,38 @@ public class ExperienceBottleItem extends Item implements ProjectileItem {
     @Override
     public InteractionResult 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 instanceof ServerLevel serverLevel) {
-            Projectile.spawnProjectileFromRotation(ThrownExperienceBottle::new, serverLevel, itemStack, user, -20.0F, 0.7F, 1.0F);
+            // Paper start - PlayerLaunchProjectileEvent
+            final Projectile.Delayed<ThrownExperienceBottle> thrownExperienceBottle = Projectile.spawnProjectileFromRotationDelayed(ThrownExperienceBottle::new, serverLevel, itemStack, user, -20.0F, 0.7F, 1.0F);
+            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.projectile().getBukkitEntity());
+            if (event.callEvent() && thrownExperienceBottle.attemptSpawn()) {
+                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)
+                );
+            } else {
+                if (user instanceof net.minecraft.server.level.ServerPlayer) {
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+                }
+                return InteractionResult.FAIL;
+            }
+            // Paper end - PlayerLaunchProjectileEvent
         }
 
-        user.awardStat(Stats.ITEM_USED.get(this));
-        itemStack.consume(1, user);
+        // Paper - PlayerLaunchProjectileEvent - moved up
         return InteractionResult.SUCCESS;
     }
 
diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
index 400ad0fa1d07c8b120e3c3b5488dfa315aa2d23f..7e308b364227dedc2d05496f5e0c90573f4a53f7 100644
--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
+++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java
@@ -33,7 +33,7 @@ public class FireworkRocketItem extends Item implements ProjectileItem {
             ItemStack itemStack = context.getItemInHand();
             Vec3 vec3 = context.getClickLocation();
             Direction direction = context.getClickedFace();
-            Projectile.spawnProjectile(
+            final Projectile.Delayed<FireworkRocketEntity> fireworkRocketEntity = Projectile.spawnProjectileDelayed( // Paper - PlayerLaunchProjectileEvent
                 new FireworkRocketEntity(
                     level,
                     context.getPlayer(),
@@ -45,7 +45,12 @@ public class FireworkRocketItem extends Item implements ProjectileItem {
                 serverLevel,
                 itemStack, f -> f.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID()  // Paper - firework api - assign spawning entity uuid
             );
-            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.projectile().getBukkitEntity());
+            if (!event.callEvent() || fireworkRocketEntity.attemptSpawn()) return InteractionResult.PASS;
+            if (event.shouldConsume() && !context.getPlayer().hasInfiniteMaterials()) 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.SUCCESS;
diff --git a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java
index 7a5045469bc2d383ed087dcc094b6f97df4ec7ab..fa92a1346825f00a585503d0a0825711fe3f754e 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 InteractionResult use(Level world, Player user, InteractionHand hand) {
+        // Paper start - PlayerLaunchProjectileEvent
+        final InteractionResult wrapper = super.use(world, user, hand);
+        if (wrapper instanceof InteractionResult.Fail) return wrapper;
+        // Paper end - PlayerLaunchProjectileEvent
         world.playSound(
             null,
             user.getX(),
@@ -34,6 +38,6 @@ public class LingeringPotionItem extends ThrowablePotionItem {
             0.5F,
             0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
         );
-        return super.use(world, user, hand);
+        return wrapper; // Paper - PlayerLaunchProjectileEvent
     }
 }
diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java
index ada9bc42a788b5f472324a0765edf5766d729784..57872ebef6beb8cdc03c9f8f19de94652ee19062 100644
--- a/src/main/java/net/minecraft/world/item/SnowballItem.java
+++ b/src/main/java/net/minecraft/world/item/SnowballItem.java
@@ -26,17 +26,26 @@ public class SnowballItem extends Item implements ProjectileItem {
         // CraftBukkit start - moved down
         // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
         if (world instanceof ServerLevel worldserver) {
-            if (Projectile.spawnProjectileFromRotation(Snowball::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F).isAlive()) {
-                itemstack.consume(1, user);
+            // Paper start - PlayerLaunchProjectileEvent
+            final Projectile.Delayed<Snowball> snowball = Projectile.spawnProjectileFromRotationDelayed(Snowball::new, worldserver, itemstack, user, 0.0F, 1.5F, 1.0F);
+            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) snowball.projectile().getBukkitEntity());
+            if (event.callEvent() && snowball.attemptSpawn()) {
+                user.awardStat(Stats.ITEM_USED.get(this));
+                if (event.shouldConsume()) {
+                    itemstack.consume(1, user);
+                } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+                    ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+                }
+            // Paper end - 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) {
+            } else { if (user instanceof net.minecraft.server.level.ServerPlayer) { // Paper - PlayerLaunchProjectileEvent - return fail
                 ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
-            }
+            } return InteractionResult.FAIL; } // Paper - PlayerLaunchProjectileEvent - return fail
             // CraftBukkit end
         }
 
-        user.awardStat(Stats.ITEM_USED.get(this));
+        // Paper - PlayerLaunchProjectileEvent - moved up
         // itemstack.consume(1, entityhuman); // CraftBukkit - moved up
         return InteractionResult.SUCCESS;
     }
diff --git a/src/main/java/net/minecraft/world/item/SplashPotionItem.java b/src/main/java/net/minecraft/world/item/SplashPotionItem.java
index 6d622d276a632c9c29ab04a01fbe7adbf10c35cd..577e66a7ff64d9569ee2402ecc26b0aa1105fe9a 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 InteractionResult use(Level world, Player user, InteractionHand hand) {
+        // Paper start - PlayerLaunchProjectileEvent
+        final InteractionResult wrapper = super.use(world, user, hand);
+        if (wrapper instanceof InteractionResult.Fail) return wrapper;
+        // Paper end - PlayerLaunchProjectileEvent
         world.playSound(
             null,
             user.getX(),
@@ -24,6 +28,6 @@ public class SplashPotionItem extends ThrowablePotionItem {
             0.5F,
             0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
         );
-        return super.use(world, user, hand);
+        return wrapper; // Paper - PlayerLaunchProjectileEvent
     }
 }
diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java
index e3eb733f18c23ae3fcc4c271843d285b217d1a7d..fa9d2ae44fcdd06f8f33cd14ffca422b20a01451 100644
--- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java
+++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java
@@ -20,11 +20,28 @@ public class ThrowablePotionItem extends PotionItem implements ProjectileItem {
     public InteractionResult use(Level world, Player user, InteractionHand hand) {
         ItemStack itemStack = user.getItemInHand(hand);
         if (world instanceof ServerLevel serverLevel) {
-            Projectile.spawnProjectileFromRotation(ThrownPotion::new, serverLevel, itemStack, user, -20.0F, 0.5F, 1.0F);
+            // Paper start - PlayerLaunchProjectileEvent
+            final Projectile.Delayed<ThrownPotion> thrownPotion = Projectile.spawnProjectileFromRotationDelayed(ThrownPotion::new, serverLevel, itemStack, user, -20.0F, 0.5F, 1.0F);
+            // 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.projectile().getBukkitEntity());
+            if (event.callEvent() && thrownPotion.attemptSpawn()) {
+                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 InteractionResult.FAIL;
+            }
+            // Paper end - PlayerLaunchProjectileEvent
         }
 
-        user.awardStat(Stats.ITEM_USED.get(this));
-        itemStack.consume(1, user);
+        // Paper - PlayerLaunchProjectileEvent - move up
         return InteractionResult.SUCCESS;
     }
 
diff --git a/src/main/java/net/minecraft/world/item/TridentItem.java b/src/main/java/net/minecraft/world/item/TridentItem.java
index 22aa715c4ef615c2c9d795cc2e11b7099d5167da..8b9a93ef71164cce8a616735b71d96d37e83b1a8 100644
--- a/src/main/java/net/minecraft/world/item/TridentItem.java
+++ b/src/main/java/net/minecraft/world/item/TridentItem.java
@@ -87,21 +87,26 @@ public class TridentItem extends Item implements ProjectileItem {
 
                         // itemstack.hurtWithoutBreaking(1, entityhuman); // CraftBukkit - moved down
                         if (f == 0.0F) {
-                            ThrownTrident entitythrowntrident = (ThrownTrident) Projectile.spawnProjectileFromRotation(ThrownTrident::new, worldserver, stack, entityhuman, 0.0F, 2.5F, 1.0F);
-                            // CraftBukkit start
-                            if (entitythrowntrident.isRemoved()) {
+                            // Paper start - PlayerLaunchProjectileEvent
+                            Projectile.Delayed<ThrownTrident> tridentDelayed = Projectile.spawnProjectileFromRotationDelayed(ThrownTrident::new, worldserver, stack, entityhuman, 0.0F, 2.5F, 1.0F);
+                            // 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) tridentDelayed.projectile().getBukkitEntity());
+                            if (!event.callEvent() || !tridentDelayed.attemptSpawn()) {
+                                // CraftBukkit start
+                            // Paper end - PlayerLaunchProjectileEvent
                                 if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) {
                                     ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory();
                                 }
                                 return false;
                             }
-                            stack.hurtWithoutBreaking(1, entityhuman);
+                            ThrownTrident entitythrowntrident = tridentDelayed.projectile(); // Paper - PlayerLaunchProjectileEvent
+                            if (event.shouldConsume()) stack.hurtWithoutBreaking(1, entityhuman); // Paper - PlayerLaunchProjectileEvent
                             entitythrowntrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved
                             // CraftBukkit end
 
                             if (entityhuman.hasInfiniteMaterials()) {
                                 entitythrowntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
-                            } else {
+                            } else if (event.shouldConsume()) { // Paper - PlayerLaunchProjectileEvent
                                 entityhuman.getInventory().removeItem(stack);
                             }
 
diff --git a/src/main/java/net/minecraft/world/item/WindChargeItem.java b/src/main/java/net/minecraft/world/item/WindChargeItem.java
index 79fdb78a4c3c7e324f0ed84a3dad9a3a80a6456a..0ce52d239b5bfb63e09cf5df679eee177f7bc5b0 100644
--- a/src/main/java/net/minecraft/world/item/WindChargeItem.java
+++ b/src/main/java/net/minecraft/world/item/WindChargeItem.java
@@ -25,7 +25,7 @@ public class WindChargeItem extends Item implements ProjectileItem {
     public InteractionResult use(Level world, Player user, InteractionHand hand) {
         ItemStack itemStack = user.getItemInHand(hand);
         if (world instanceof ServerLevel serverLevel) {
-            Projectile.spawnProjectileFromRotation(
+            final Projectile.Delayed<WindCharge> windCharge = Projectile.spawnProjectileFromRotationDelayed( // Paper - PlayerLaunchProjectileEvent
                 (world2, shooter, stack) -> new WindCharge(user, world, user.position().x(), user.getEyePosition().y(), user.position().z()),
                 serverLevel,
                 itemStack,
@@ -34,6 +34,21 @@ public class WindChargeItem extends Item implements ProjectileItem {
                 1.5F,
                 1.0F
             );
+            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.projectile().getBukkitEntity());
+            if (!event.callEvent() || !windCharge.attemptSpawn()) {
+                user.containerMenu.sendAllDataToRemote();
+                if (user instanceof net.minecraft.server.level.ServerPlayer player) {
+                    player.connection.send(new net.minecraft.network.protocol.game.ClientboundCooldownPacket(user.getCooldowns().getCooldownGroup(itemStack), 0)); // prevent visual desync of cooldown on the slot
+                }
+                return InteractionResult.FAIL;
+            }
+
+            user.awardStat(Stats.ITEM_USED.get(this));
+            if (event.shouldConsume()) itemStack.consume(1, user);
+            else if (!user.hasInfiniteMaterials()) {
+                user.containerMenu.sendAllDataToRemote();
+            }
+            // Paper end - PlayerLaunchProjectileEvent
         }
 
         world.playSound(
@@ -46,8 +61,6 @@ public class WindChargeItem extends Item implements ProjectileItem {
             0.5F,
             0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
         );
-        user.awardStat(Stats.ITEM_USED.get(this));
-        itemStack.consume(1, user);
         return InteractionResult.SUCCESS;
     }