Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit 1a4e892

Browse files
authored
Implement ProjectileImpactEvent (#168)
1 parent 6702c75 commit 1a4e892

9 files changed

Lines changed: 395 additions & 1 deletion

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.minecraftforge.event.entity;
21+
22+
import net.minecraft.entity.Entity;
23+
import net.minecraft.entity.projectile.ExplosiveProjectileEntity;
24+
import net.minecraft.entity.projectile.ProjectileEntity;
25+
import net.minecraft.entity.thrown.ThrownEntity;
26+
import net.minecraft.util.hit.HitResult;
27+
28+
/**
29+
* This event is fired when a projectile entity impacts something.
30+
*
31+
* <p>Subclasses of this event exist for more specific types of projectile.</p>
32+
*
33+
* <p>This event is fired for all vanilla projectiles by Patchwork.
34+
* Custom projectiles should fire this event via {@link net.patchworkmc.impl.event.entity.EntityEvents}, check the result,
35+
* and cancel the impact if false.</p>
36+
*
37+
* <p>This event is cancelable. When canceled, the impact will not be processed.
38+
* Killing or other handling of the entity after event cancellation is up to the modder.</p>
39+
*
40+
* <p>This event is fired on the {@link net.minecraftforge.common.MinecraftForge#EVENT_BUS}.</p>
41+
*/
42+
public class ProjectileImpactEvent extends EntityEvent {
43+
private final HitResult ray;
44+
45+
public ProjectileImpactEvent(Entity entity, HitResult ray) {
46+
super(entity);
47+
this.ray = ray;
48+
}
49+
50+
@Override
51+
public boolean isCancelable() {
52+
return true;
53+
}
54+
55+
public HitResult getRayTraceResult() {
56+
return ray;
57+
}
58+
59+
public static class Arrow extends ProjectileImpactEvent {
60+
private final ProjectileEntity arrow;
61+
62+
public Arrow(ProjectileEntity arrow, HitResult ray) {
63+
super(arrow, ray);
64+
this.arrow = arrow;
65+
}
66+
67+
public ProjectileEntity getArrow() {
68+
return arrow;
69+
}
70+
}
71+
72+
public static class Fireball extends ProjectileImpactEvent {
73+
private final ExplosiveProjectileEntity fireball;
74+
75+
public Fireball(ExplosiveProjectileEntity fireball, HitResult ray) {
76+
super(fireball, ray);
77+
this.fireball = fireball;
78+
}
79+
80+
public ExplosiveProjectileEntity getFireball() {
81+
return fireball;
82+
}
83+
}
84+
85+
public static class Throwable extends ProjectileImpactEvent {
86+
private final ThrownEntity throwable;
87+
88+
public Throwable(ThrownEntity throwable, HitResult ray) {
89+
super(throwable, ray);
90+
this.throwable = throwable;
91+
}
92+
93+
public ThrownEntity getThrowable() {
94+
return throwable;
95+
}
96+
}
97+
}

patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/EntityEvents.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import net.minecraftforge.common.extensions.IForgeItem;
2727
import net.minecraftforge.event.entity.EntityEvent;
2828
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
29+
import net.minecraftforge.event.entity.ProjectileImpactEvent;
2930
import net.minecraftforge.event.entity.living.AnimalTameEvent;
3031
import net.minecraftforge.event.entity.living.LivingAttackEvent;
3132
import net.minecraftforge.event.entity.living.LivingDamageEvent;
@@ -56,10 +57,14 @@
5657
import net.minecraft.entity.mob.MobEntity;
5758
import net.minecraft.entity.passive.AnimalEntity;
5859
import net.minecraft.entity.player.PlayerEntity;
60+
import net.minecraft.entity.projectile.ExplosiveProjectileEntity;
61+
import net.minecraft.entity.projectile.ProjectileEntity;
62+
import net.minecraft.entity.thrown.ThrownEntity;
5963
import net.minecraft.item.ItemStack;
6064
import net.minecraft.text.Text;
6165
import net.minecraft.util.ActionResult;
6266
import net.minecraft.util.Hand;
67+
import net.minecraft.util.hit.HitResult;
6368
import net.minecraft.world.IWorld;
6469
import net.minecraft.world.MobSpawnerLogic;
6570
import net.minecraft.world.World;
@@ -196,6 +201,22 @@ public static boolean onAnimalTame(AnimalEntity animal, PlayerEntity tamer) {
196201
return MinecraftForge.EVENT_BUS.post(new AnimalTameEvent(animal, tamer));
197202
}
198203

204+
public static boolean onProjectileImpact(Entity entity, HitResult ray) {
205+
return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent(entity, ray));
206+
}
207+
208+
public static boolean onProjectileImpact(ProjectileEntity arrow, HitResult ray) {
209+
return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent.Arrow(arrow, ray));
210+
}
211+
212+
public static boolean onProjectileImpact(ExplosiveProjectileEntity fireball, HitResult ray) {
213+
return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent.Fireball(fireball, ray));
214+
}
215+
216+
public static boolean onProjectileImpact(ThrownEntity throwable, HitResult ray) {
217+
return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent.Throwable(throwable, ray));
218+
}
219+
199220
@Override
200221
public void onInitialize() {
201222
UseItemCallback.EVENT.register((player, world, hand) -> {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.patchworkmc.mixin.event.entity;
21+
22+
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.Shadow;
24+
import org.spongepowered.asm.mixin.injection.At;
25+
import org.spongepowered.asm.mixin.injection.Redirect;
26+
27+
import net.minecraft.entity.projectile.ExplosiveProjectileEntity;
28+
import net.minecraft.util.hit.HitResult;
29+
30+
import net.patchworkmc.impl.event.entity.EntityEvents;
31+
32+
@Mixin(ExplosiveProjectileEntity.class)
33+
public abstract class MixinExplosiveProjectileEntity {
34+
@Shadow
35+
protected abstract void onCollision(HitResult hitResult);
36+
37+
/**
38+
* Mixin to the redirect the onCollision method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}.
39+
*
40+
* <p>Note: In future versions, the @Redirect should be replaced with a @ModifyVariable to the bl flag.</p>
41+
*/
42+
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/ExplosiveProjectileEntity;onCollision(Lnet/minecraft/util/hit/HitResult;)V"))
43+
private void hookTick(ExplosiveProjectileEntity entity, HitResult hitResult) {
44+
if (!EntityEvents.onProjectileImpact(entity, hitResult)) {
45+
this.onCollision(hitResult);
46+
}
47+
}
48+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.patchworkmc.mixin.event.entity;
21+
22+
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.injection.At;
24+
import org.spongepowered.asm.mixin.injection.Inject;
25+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
26+
27+
import net.minecraft.entity.projectile.LlamaSpitEntity;
28+
import net.minecraft.util.hit.HitResult;
29+
30+
import net.patchworkmc.impl.event.entity.EntityEvents;
31+
32+
@Mixin(LlamaSpitEntity.class)
33+
public class MixinLlamaSpitEntity {
34+
/**
35+
* Mixin to the projectile hit method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}.
36+
*
37+
* <p>This will cancel the rest of method_7481 if the forge event pipeline requests it, but a Fabric mod with higher
38+
* priority can still inject into its head.</p>
39+
*
40+
* <p>This mixin is implemented differently from the other onProjectileImpact mixins because there is no check that
41+
* the hit didn't miss before calling onHit, so we need to maintain calls to onHit for missed shots, but still need
42+
* to check that it didn't miss before calling onProjectileImpact.</p>
43+
*/
44+
@Inject(method = "method_7481", at = @At("HEAD"), cancellable = true)
45+
private void hookHit(HitResult hitResult, CallbackInfo callback) {
46+
LlamaSpitEntity entity = (LlamaSpitEntity) (Object) this;
47+
48+
if (EntityEvents.onProjectileImpact(entity, hitResult)) {
49+
callback.cancel();
50+
}
51+
}
52+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.patchworkmc.mixin.event.entity;
21+
22+
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.injection.At;
24+
import org.spongepowered.asm.mixin.injection.Inject;
25+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
26+
27+
import net.minecraft.entity.projectile.ProjectileEntity;
28+
import net.minecraft.util.hit.HitResult;
29+
30+
import net.patchworkmc.impl.event.entity.EntityEvents;
31+
32+
@Mixin(ProjectileEntity.class)
33+
public class MixinProjectileEntity {
34+
/**
35+
* Mixin to the projectile hit method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}.
36+
*
37+
* <p>This will cancel the rest of onHit if the event pipeline requests it, but a Fabric mod with higher
38+
* priority can still inject into its head.</p>
39+
*
40+
* <p>This mixin is implemented differently from the other onProjectileImpact mixins because there is no check that
41+
* the hit didn't miss before calling onHit, so we need to maintain calls to onHit for missed shots, but still need
42+
* to check that it didn't miss before calling onProjectileImpact.</p>
43+
*/
44+
@Inject(method = "onHit(Lnet/minecraft/util/hit/HitResult;)V", at = @At("HEAD"), cancellable = true)
45+
private void hookHit(HitResult hitResult, CallbackInfo callback) {
46+
if (hitResult.getType() != HitResult.Type.MISS) {
47+
ProjectileEntity entity = (ProjectileEntity) (Object) this;
48+
49+
if (EntityEvents.onProjectileImpact(entity, hitResult)) {
50+
callback.cancel();
51+
}
52+
}
53+
}
54+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.patchworkmc.mixin.event.entity;
21+
22+
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.Shadow;
24+
import org.spongepowered.asm.mixin.injection.At;
25+
import org.spongepowered.asm.mixin.injection.Redirect;
26+
27+
import net.minecraft.entity.projectile.ShulkerBulletEntity;
28+
import net.minecraft.util.hit.HitResult;
29+
30+
import net.patchworkmc.impl.event.entity.EntityEvents;
31+
32+
@Mixin(ShulkerBulletEntity.class)
33+
public abstract class MixinShulkerBulletEntity {
34+
@Shadow
35+
protected abstract void onHit(HitResult hitResult);
36+
37+
/**
38+
* Mixin to the redirect the ShulkerBulletEntity hit method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}.
39+
*
40+
* <p>Note: In future versions, the @Redirect should be replaced with a @ModifyVariable to the bl flag.</p>
41+
*/
42+
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/ShulkerBulletEntity;onHit(Lnet/minecraft/util/hit/HitResult;)V"))
43+
private void hookTick(ShulkerBulletEntity entity, HitResult hitResult) {
44+
if (!EntityEvents.onProjectileImpact(entity, hitResult)) {
45+
this.onHit(hitResult);
46+
}
47+
}
48+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package net.patchworkmc.mixin.event.entity;
21+
22+
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.Shadow;
24+
import org.spongepowered.asm.mixin.injection.At;
25+
import org.spongepowered.asm.mixin.injection.Redirect;
26+
27+
import net.minecraft.entity.thrown.ThrownEntity;
28+
import net.minecraft.util.hit.HitResult;
29+
30+
import net.patchworkmc.impl.event.entity.EntityEvents;
31+
32+
@Mixin(ThrownEntity.class)
33+
public abstract class MixinThrownEntity {
34+
@Shadow
35+
protected abstract void onCollision(HitResult hitResult);
36+
37+
/**
38+
* Mixin to the redirect the ThrownEntity hit method, to call {@link net.minecraftforge.event.entity.ProjectileImpactEvent}.
39+
*
40+
* <p>Note: In future versions, the @Redirect should be replaced with a @ModifyVariable to the bl flag.</p>
41+
*/
42+
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/thrown/ThrownEntity;onCollision(Lnet/minecraft/util/hit/HitResult;)V"))
43+
private void hookTick(ThrownEntity entity, HitResult hitResult) {
44+
if (!EntityEvents.onProjectileImpact(entity, hitResult)) {
45+
this.onCollision(hitResult);
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)