Skip to content

Commit 584f5f4

Browse files
authored
Better ProjectileHitEvent API (#26)
1 parent 945c503 commit 584f5f4

2 files changed

Lines changed: 389 additions & 0 deletions

File tree

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
From 2326dfc8d8961b6d6da4772593c5fa78e3456e5d Mon Sep 17 00:00:00 2001
2+
From: Vanolex <vanolex@vanolex.net>
3+
Date: Wed, 21 Jan 2026 01:33:31 +0100
4+
Subject: [PATCH] Better-ProjectileHitEvent-API
5+
6+
7+
diff --git a/src/main/java/dev/rocco/kig/paper/api/event/ProjectileCollideEvent.java b/src/main/java/dev/rocco/kig/paper/api/event/ProjectileCollideEvent.java
8+
index 4152109c..0ab8d44a 100644
9+
--- a/src/main/java/dev/rocco/kig/paper/api/event/ProjectileCollideEvent.java
10+
+++ b/src/main/java/dev/rocco/kig/paper/api/event/ProjectileCollideEvent.java
11+
@@ -4,21 +4,21 @@ import org.bukkit.entity.Entity;
12+
import org.bukkit.entity.Projectile;
13+
import org.bukkit.event.Cancellable;
14+
import org.bukkit.event.HandlerList;
15+
-import org.bukkit.event.entity.EntityEvent;
16+
17+
/**
18+
* Fired when a {@link Projectile} is about to collide with an {@link Entity}.
19+
* Cancelling the event will make the projectile go through the entity.
20+
+ *
21+
+ * @deprecated use {@link ProjectilePreHitEntityEvent}
22+
*/
23+
-public class ProjectileCollideEvent extends EntityEvent implements Cancellable {
24+
+@Deprecated
25+
+public class ProjectileCollideEvent extends ProjectilePreHitEntityEvent implements Cancellable {
26+
private static final HandlerList handlers = new HandlerList();
27+
28+
- private final Entity collided;
29+
private boolean cancel;
30+
31+
public ProjectileCollideEvent(Projectile projectile, Entity collided) {
32+
- super(projectile);
33+
- this.collided = collided;
34+
+ super(projectile, collided);
35+
}
36+
37+
@Override
38+
@@ -36,7 +36,7 @@ public class ProjectileCollideEvent extends EntityEvent implements Cancellable {
39+
}
40+
41+
public Entity getCollided() {
42+
- return collided;
43+
+ return getHitEntity();
44+
}
45+
46+
@Override
47+
diff --git a/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitBlockEvent.java b/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitBlockEvent.java
48+
new file mode 100644
49+
index 00000000..c3acdf9d
50+
--- /dev/null
51+
+++ b/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitBlockEvent.java
52+
@@ -0,0 +1,42 @@
53+
+package dev.rocco.kig.paper.api.event;
54+
+
55+
+import org.bukkit.block.Block;
56+
+import org.bukkit.block.BlockFace;
57+
+import org.bukkit.entity.Projectile;
58+
+import org.bukkit.event.entity.ProjectileHitEvent;
59+
+
60+
+/**
61+
+ * Called when a projectile hits a block. Called every tick when phasing through blocks.
62+
+ */
63+
+public class ProjectilePreHitBlockEvent extends ProjectilePreHitEvent {
64+
+ private final Block hitBlock;
65+
+ private final BlockFace hitFace;
66+
+
67+
+ public ProjectilePreHitBlockEvent(Projectile projectile, Block hitBlock, BlockFace hitFace) { this(projectile,hitBlock,hitFace,false); }
68+
+ public ProjectilePreHitBlockEvent(Projectile projectile, Block hitBlock, BlockFace hitFace, boolean cancelled) {
69+
+ super(projectile, cancelled);
70+
+ this.hitBlock = hitBlock;
71+
+ this.hitFace = hitFace;
72+
+ }
73+
+
74+
+ /**
75+
+ * Gets the block that is about to be hit.
76+
+ * <p>
77+
+ * Note: modifying the block does not change the outcome of the event.
78+
+ *
79+
+ * @return the block that is about to be hit
80+
+ */
81+
+ public Block getHitBlock() {
82+
+ return hitBlock;
83+
+ }
84+
+
85+
+ /**
86+
+ * Gets the face of the block that is about to be hit.
87+
+ *
88+
+ * @return the face of the block that is about to be hit
89+
+ */
90+
+ public BlockFace getHitFace() {
91+
+ return hitFace;
92+
+ }
93+
+}
94+
+
95+
diff --git a/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitEntityEvent.java b/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitEntityEvent.java
96+
new file mode 100644
97+
index 00000000..c04ad72a
98+
--- /dev/null
99+
+++ b/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitEntityEvent.java
100+
@@ -0,0 +1,27 @@
101+
+package dev.rocco.kig.paper.api.event;
102+
+
103+
+import org.bukkit.entity.Entity;
104+
+import org.bukkit.entity.Projectile;
105+
+
106+
+/**
107+
+ * Called when a projectile is about to hit an entity.
108+
+ */
109+
+public class ProjectilePreHitEntityEvent extends ProjectilePreHitEvent {
110+
+
111+
+ private final Entity hitEntity;
112+
+
113+
+ public ProjectilePreHitEntityEvent(Projectile projectile, Entity hitEntity) { this(projectile, hitEntity, false); }
114+
+ public ProjectilePreHitEntityEvent(Projectile projectile, Entity hitEntity, boolean cancelled) {
115+
+ super(projectile, cancelled);
116+
+ this.hitEntity = hitEntity;
117+
+ }
118+
+
119+
+ /**
120+
+ * Gets the entity that is about to be hit.
121+
+ *
122+
+ * @return the entity that is about to be hit
123+
+ */
124+
+ public Entity getHitEntity() {
125+
+ return hitEntity;
126+
+ }
127+
+}
128+
diff --git a/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitEvent.java b/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitEvent.java
129+
new file mode 100644
130+
index 00000000..4726a60e
131+
--- /dev/null
132+
+++ b/src/main/java/dev/rocco/kig/paper/api/event/ProjectilePreHitEvent.java
133+
@@ -0,0 +1,60 @@
134+
+package dev.rocco.kig.paper.api.event;
135+
+
136+
+import org.bukkit.entity.Projectile;
137+
+import org.bukkit.event.Cancellable;
138+
+import org.bukkit.event.HandlerList;
139+
+import org.bukkit.event.entity.EntityEvent;
140+
+
141+
+/**
142+
+ * Called when a projectile is about to hit something (Entity or Block).
143+
+ * Cancelling disables collisions.
144+
+ */
145+
+public class ProjectilePreHitEvent extends EntityEvent implements Cancellable {
146+
+ private static final HandlerList handlers = new HandlerList();
147+
+ private boolean cancelled;
148+
+
149+
+ public ProjectilePreHitEvent(final Projectile projectile) { this(projectile, false); }
150+
+ public ProjectilePreHitEvent(final Projectile projectile, final boolean cancelled) {
151+
+ super(projectile);
152+
+ this.cancelled = cancelled;
153+
+ }
154+
+
155+
+ @Override
156+
+ /**
157+
+ * Gets the projectile involved in this event.
158+
+ *
159+
+ * @return the projectile involved in this event
160+
+ */
161+
+ public Projectile getEntity() {
162+
+ return (Projectile) entity;
163+
+ }
164+
+
165+
+ @Override
166+
+ public HandlerList getHandlers() {
167+
+ return handlers;
168+
+ }
169+
+
170+
+ /**
171+
+ * Gets the handler list for this event.
172+
+ *
173+
+ * @return the handler list
174+
+ */
175+
+ public static HandlerList getHandlerList() {
176+
+ return handlers;
177+
+ }
178+
+
179+
+ @Override
180+
+ public boolean isCancelled() {
181+
+ return cancelled;
182+
+ }
183+
+
184+
+ @Override
185+
+ /**
186+
+ * Sets whether to cancel the collision.
187+
+ *
188+
+ * @param cancel true if the collision should be cancelled
189+
+ */
190+
+ public void setCancelled(boolean cancel) {
191+
+ cancelled = cancel;
192+
+ }
193+
+}
194+
--
195+
2.51.0.windows.1
196+
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
From 9cef6a2f9bcb79a176f428c9d37a8ed1c3c4cf1d Mon Sep 17 00:00:00 2001
2+
From: Vanolex <vanolex@vanolex.net>
3+
Date: Sat, 24 Jan 2026 00:30:00 +0100
4+
Subject: [PATCH] Better-ProjectileHitEvent-API
5+
6+
7+
diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java
8+
index 78bb8bfbe..928bbbf7e 100644
9+
--- a/src/main/java/net/minecraft/server/EntityArrow.java
10+
+++ b/src/main/java/net/minecraft/server/EntityArrow.java
11+
@@ -1,9 +1,10 @@
12+
package net.minecraft.server;
13+
14+
import dev.rocco.kig.paper.api.event.PlayerCheckCriticalEvent;
15+
-import dev.rocco.kig.paper.api.event.ProjectileCollideEvent;
16+
+import dev.rocco.kig.paper.api.event.ProjectilePreHitEvent;
17+
import dev.rocco.kig.paper.api.particle.ProjectileEffect;
18+
import org.bukkit.Location;
19+
+import org.bukkit.craftbukkit.event.CraftEventFactory;
20+
import org.bukkit.entity.LivingEntity;
21+
import org.bukkit.entity.Player;
22+
import org.bukkit.event.entity.EntityCombustByEntityEvent;
23+
@@ -261,8 +262,13 @@ public class EntityArrow extends Entity implements IProjectile {
24+
// PaperSpigot end
25+
26+
// KigPaper start
27+
- if (movingobjectposition != null && movingobjectposition.entity != null) {
28+
- ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition.entity);
29+
+ if (movingobjectposition != null) {
30+
+ ProjectilePreHitEvent event;
31+
+ if (movingobjectposition.entity != null) {
32+
+ event = CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition.entity);
33+
+ } else {
34+
+ event = CraftEventFactory.callProjectilePreHitBlockEvent(this, movingobjectposition);
35+
+ }
36+
if (event.isCancelled()) movingobjectposition = null;
37+
}
38+
// KigPaper end
39+
diff --git a/src/main/java/net/minecraft/server/EntityFireball.java b/src/main/java/net/minecraft/server/EntityFireball.java
40+
index 7a6a0843d..4418c9784 100644
41+
--- a/src/main/java/net/minecraft/server/EntityFireball.java
42+
+++ b/src/main/java/net/minecraft/server/EntityFireball.java
43+
@@ -2,7 +2,7 @@ package net.minecraft.server;
44+
45+
import java.util.List;
46+
47+
-import dev.rocco.kig.paper.api.event.ProjectileCollideEvent;
48+
+import dev.rocco.kig.paper.api.event.ProjectilePreHitEvent;
49+
import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
50+
51+
public abstract class EntityFireball extends Entity {
52+
@@ -128,8 +128,13 @@ public abstract class EntityFireball extends Entity {
53+
}
54+
55+
// KigPaper start
56+
- if (movingobjectposition != null && movingobjectposition.entity != null) {
57+
- ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition.entity);
58+
+ if (movingobjectposition != null) {
59+
+ ProjectilePreHitEvent event;
60+
+ if (movingobjectposition.entity != null) {
61+
+ event = CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition.entity);
62+
+ } else {
63+
+ event = CraftEventFactory.callProjectilePreHitBlockEvent(this, movingobjectposition);
64+
+ }
65+
if (event.isCancelled()) movingobjectposition = null;
66+
}
67+
// KigPaper end
68+
diff --git a/src/main/java/net/minecraft/server/EntityFishingHook.java b/src/main/java/net/minecraft/server/EntityFishingHook.java
69+
index e5d2f80f6..d9dee525f 100644
70+
--- a/src/main/java/net/minecraft/server/EntityFishingHook.java
71+
+++ b/src/main/java/net/minecraft/server/EntityFishingHook.java
72+
@@ -1,8 +1,9 @@
73+
package net.minecraft.server;
74+
75+
-import dev.rocco.kig.paper.api.event.ProjectileCollideEvent;
76+
+import dev.rocco.kig.paper.api.event.ProjectilePreHitEvent;
77+
import dev.rocco.kig.paper.api.particle.ProjectileEffect;
78+
import org.bukkit.Location;
79+
+import org.bukkit.craftbukkit.event.CraftEventFactory;
80+
import org.bukkit.entity.Fish;
81+
import org.bukkit.entity.Player;
82+
import org.bukkit.event.player.PlayerFishEvent;
83+
@@ -216,8 +217,15 @@ public class EntityFishingHook extends Entity {
84+
// PaperSpigot end
85+
86+
// KigPaper start
87+
- if (movingobjectposition != null && movingobjectposition.entity != null) {
88+
- ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition.entity);
89+
+ boolean isBlockEventCancelled = false;
90+
+ if (movingobjectposition != null) {
91+
+ ProjectilePreHitEvent event;
92+
+ if (movingobjectposition.entity != null) {
93+
+ event = CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition.entity);
94+
+ } else {
95+
+ event = CraftEventFactory.callProjectilePreHitBlockEvent(this, movingobjectposition);
96+
+ isBlockEventCancelled = event.isCancelled();
97+
+ }
98+
if (event.isCancelled()) movingobjectposition = null;
99+
}
100+
// KigPaper end
101+
@@ -240,7 +248,16 @@ public class EntityFishingHook extends Entity {
102+
trailEffect.spawn(loc);
103+
}
104+
}
105+
+
106+
+
107+
+ boolean oldNoclip = this.noclip; // KigPaper
108+
+ this.noclip = this.noclip || isBlockEventCancelled; // KigPaper - allow projectiles to pass through blocks when event cancelled
109+
+
110+
this.move(this.motX, this.motY, this.motZ);
111+
+
112+
+ this.noclip = oldNoclip; // KigPaper
113+
+
114+
+
115+
float f1 = MathHelper.sqrt(this.motX * this.motX + this.motZ * this.motZ);
116+
117+
this.yaw = (float) (MathHelper.b(this.motX, this.motZ) * 180.0D / 3.1415927410125732D);
118+
diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java
119+
index 793cd1191..7692de18b 100644
120+
--- a/src/main/java/net/minecraft/server/EntityProjectile.java
121+
+++ b/src/main/java/net/minecraft/server/EntityProjectile.java
122+
@@ -2,9 +2,10 @@ package net.minecraft.server;
123+
124+
// KigPaper start
125+
126+
-import dev.rocco.kig.paper.api.event.ProjectileCollideEvent;
127+
+import dev.rocco.kig.paper.api.event.ProjectilePreHitEvent;
128+
import dev.rocco.kig.paper.api.particle.ProjectileEffect;
129+
import org.bukkit.Location;
130+
+import org.bukkit.craftbukkit.event.CraftEventFactory;
131+
import org.bukkit.entity.Player;
132+
133+
import java.util.List;
134+
@@ -179,8 +180,11 @@ public abstract class EntityProjectile extends Entity implements IProjectile {
135+
// PaperSpigot end
136+
137+
// KigPaper start
138+
- if (movingobjectposition != null && movingobjectposition.entity != null) {
139+
- ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition.entity);
140+
+ if (movingobjectposition != null) {
141+
+ ProjectilePreHitEvent event =
142+
+ movingobjectposition.entity != null ?
143+
+ CraftEventFactory.callProjectileCollideEvent(this, movingobjectposition.entity) :
144+
+ CraftEventFactory.callProjectilePreHitBlockEvent(this, movingobjectposition);
145+
if (event.isCancelled()) movingobjectposition = null;
146+
}
147+
// KigPaper end
148+
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
149+
index ff62ce025..5b495c4ea 100644
150+
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
151+
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
152+
@@ -10,6 +10,8 @@ import com.google.common.base.Function;
153+
import com.google.common.base.Functions;
154+
155+
import dev.rocco.kig.paper.api.event.ProjectileCollideEvent;
156+
+import dev.rocco.kig.paper.api.event.ProjectilePreHitBlockEvent;
157+
+import dev.rocco.kig.paper.api.event.ProjectilePreHitEntityEvent;
158+
import net.minecraft.server.*;
159+
160+
import org.bukkit.Bukkit;
161+
@@ -766,11 +768,29 @@ public class CraftEventFactory {
162+
}
163+
164+
// KigPaper start
165+
+
166+
+ /**
167+
+ * @deprecated use {@link ProjectilePreHitEntityEvent}
168+
+ */
169+
+ @Deprecated
170+
public static ProjectileCollideEvent callProjectileCollideEvent(Entity entity, Entity collided) {
171+
ProjectileCollideEvent event = new ProjectileCollideEvent((Projectile) entity.getBukkitEntity(), collided.getBukkitEntity());
172+
entity.world.getServer().getPluginManager().callEvent(event);
173+
return event;
174+
}
175+
+
176+
+ public static ProjectilePreHitEntityEvent callProjectilePreHitEntityEvent(Entity projectile, Entity hitEntity) {
177+
+ ProjectilePreHitEntityEvent event = new ProjectilePreHitEntityEvent((Projectile) projectile, hitEntity.getBukkitEntity());
178+
+ projectile.world.getServer().getPluginManager().callEvent(event);
179+
+ return event;
180+
+ }
181+
+
182+
+ public static ProjectilePreHitBlockEvent callProjectilePreHitBlockEvent(Entity projectile, MovingObjectPosition movingObjectPosition) {
183+
+ org.bukkit.block.Block block = projectile.world.getWorld().getBlockAt(movingObjectPosition.a().getX(), movingObjectPosition.a().getY(), movingObjectPosition.a().getZ());
184+
+ ProjectilePreHitBlockEvent event = new ProjectilePreHitBlockEvent((Projectile) projectile.getBukkitEntity(), block, CraftBlock.notchToBlockFace(movingObjectPosition.direction));
185+
+ projectile.world.getServer().getPluginManager().callEvent(event);
186+
+ return event;
187+
+ }
188+
// KigPaper end
189+
190+
public static ExpBottleEvent callExpBottleEvent(Entity entity, int exp) {
191+
--
192+
2.51.0.windows.1
193+

0 commit comments

Comments
 (0)