Skip to content

Commit 614e9ac

Browse files
AeltumnlynxplayLulu13022002
authored
Improve APIs around riptide tridents (#12996)
Co-authored-by: Bjarne Koll <git@lynxplay.dev> Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
1 parent 52d9a22 commit 614e9ac

File tree

5 files changed

+121
-4
lines changed

5 files changed

+121
-4
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package io.papermc.paper.event.entity;
2+
3+
import org.bukkit.entity.LivingEntity;
4+
import org.bukkit.event.Cancellable;
5+
import org.bukkit.event.HandlerList;
6+
import org.bukkit.event.entity.EntityEvent;
7+
import org.jetbrains.annotations.ApiStatus;
8+
import org.jspecify.annotations.NullMarked;
9+
10+
/**
11+
* Called when a {@link LivingEntity} attempts to perform an automatic spin attack
12+
* against a target entity.
13+
*/
14+
@NullMarked
15+
public class EntityAttemptSpinAttackEvent extends EntityEvent implements Cancellable {
16+
17+
private static final HandlerList HANDLER_LIST = new HandlerList();
18+
19+
private final LivingEntity target;
20+
21+
private boolean cancelled;
22+
23+
@ApiStatus.Internal
24+
public EntityAttemptSpinAttackEvent(final LivingEntity entity, final LivingEntity target) {
25+
super(entity);
26+
this.target = target;
27+
}
28+
29+
@Override
30+
public LivingEntity getEntity() {
31+
return (LivingEntity) this.entity;
32+
}
33+
34+
/**
35+
* Returns the entity that is being attacked
36+
* in the spin attack.
37+
*
38+
* @return the entity being attacked
39+
*/
40+
public LivingEntity getTarget() {
41+
return this.target;
42+
}
43+
44+
/**
45+
* {@inheritDoc}
46+
* <p>
47+
* It should be noted that both the client and server independently check
48+
* for a spin attack. Cancelling this on the server means the animation is not
49+
* interrupted and no attack is performed, but the client will still collide
50+
* and bounce away.
51+
*/
52+
@Override
53+
public void setCancelled(boolean cancelled) {
54+
this.cancelled = cancelled;
55+
}
56+
57+
@Override
58+
public boolean isCancelled() {
59+
return this.cancelled;
60+
}
61+
62+
@Override
63+
public HandlerList getHandlers() {
64+
return HANDLER_LIST;
65+
}
66+
67+
public static HandlerList getHandlerList() {
68+
return HANDLER_LIST;
69+
}
70+
}

paper-api/src/main/java/org/bukkit/event/player/PlayerRiptideEvent.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.bukkit.event.player;
22

33
import org.bukkit.entity.Player;
4+
import org.bukkit.event.Cancellable;
45
import org.bukkit.event.HandlerList;
56
import org.bukkit.inventory.ItemStack;
67
import org.bukkit.util.Vector;
@@ -14,13 +15,15 @@
1415
* N.B. the riptide action is currently performed client side, so manipulating
1516
* the player in this event may have undesired effects.
1617
*/
17-
public class PlayerRiptideEvent extends PlayerEvent {
18+
public class PlayerRiptideEvent extends PlayerEvent implements Cancellable {
1819

1920
private static final HandlerList HANDLER_LIST = new HandlerList();
2021

2122
private final ItemStack item;
2223
private final Vector velocity;
2324

25+
private boolean cancelled;
26+
2427
@ApiStatus.Internal
2528
public PlayerRiptideEvent(@NotNull final Player player, @NotNull final ItemStack item, @NotNull Vector velocity) {
2629
super(player);
@@ -54,6 +57,16 @@ public Vector getVelocity() {
5457
return this.velocity.clone();
5558
}
5659

60+
@Override
61+
public boolean isCancelled() {
62+
return this.cancelled;
63+
}
64+
65+
@Override
66+
public void setCancelled(boolean cancel) {
67+
this.cancelled = cancel;
68+
}
69+
5770
@NotNull
5871
@Override
5972
public HandlerList getHandlers() {

paper-server/patches/sources/net/minecraft/world/entity/LivingEntity.java.patch

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,40 @@
15401540
this.doPush(entity1);
15411541
}
15421542
}
1543+
@@ -2954,16 +_,32 @@
1544+
protected void checkAutoSpinAttack(AABB boundingBoxBeforeSpin, AABB boundingBoxAfterSpin) {
1545+
AABB aabb = boundingBoxBeforeSpin.minmax(boundingBoxAfterSpin);
1546+
List<Entity> entities = this.level().getEntities(this, aabb);
1547+
+ int skippedAttackedEntitiesCounter = 0; // Paper - entity attempt spin attack event / hidden entities - count entities that are retroactively not part of the list
1548+
if (!entities.isEmpty()) {
1549+
for (Entity entity : entities) {
1550+
+ // Paper start - entity attempt spin attack event / hidden entities - skip hidden entities
1551+
+ if (this instanceof final ServerPlayer serverPlayer && !serverPlayer.getBukkitEntity().canSee(entity.getBukkitEntity())) {
1552+
+ ++skippedAttackedEntitiesCounter;
1553+
+ continue;
1554+
+ }
1555+
+ // Paper end - entity attempt spin attack event / hidden entities - skip hidden entities
1556+
if (entity instanceof LivingEntity) {
1557+
+ // Paper start - entity attempt spin attack event / hidden entities - skip hidden entities
1558+
+ if (!new io.papermc.paper.event.entity.EntityAttemptSpinAttackEvent(
1559+
+ getBukkitLivingEntity(),
1560+
+ ((LivingEntity) entity).getBukkitLivingEntity()
1561+
+ ).callEvent()) {
1562+
+ ++skippedAttackedEntitiesCounter;
1563+
+ continue;
1564+
+ }
1565+
+ // Paper end - entity attempt spin attack event / hidden entities - skip hidden entities
1566+
this.doAutoAttackOnTouch((LivingEntity)entity);
1567+
this.autoSpinAttackTicks = 0;
1568+
this.setDeltaMovement(this.getDeltaMovement().scale(-0.2));
1569+
break;
1570+
}
1571+
}
1572+
- } else if (this.horizontalCollision) {
1573+
+ } if (this.horizontalCollision && skippedAttackedEntitiesCounter == entities.size()) { // Paper - entity attempt spin attack event - only check if above list was either empty (size is 0, counter is 0 because of it) or filled completely with skipped entities.
1574+
this.autoSpinAttackTicks = 0;
1575+
}
1576+
15431577
@@ -2987,9 +_,16 @@
15441578

15451579
@Override

paper-server/patches/sources/net/minecraft/world/item/TridentItem.java.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
f *= tridentSpinAttackStrength / squareRoot;
4747
f1 *= tridentSpinAttackStrength / squareRoot;
4848
f2 *= tridentSpinAttackStrength / squareRoot;
49-
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerRiptideEvent(player, stack, f, f1, f2); // CraftBukkit
49+
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerRiptideEvent(player, stack, f, f1, f2)) return false; // Paper - Add player riptide event
5050
player.push(f, f1, f2);
5151
player.startAutoSpinAttack(20, 8.0F, stack);
5252
if (player.onGround()) {

paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,9 +1559,9 @@ public static PlayerLeashEntityEvent callPlayerLeashEntityEvent(Entity entity, E
15591559
return event;
15601560
}
15611561

1562-
public static void callPlayerRiptideEvent(net.minecraft.world.entity.player.Player player, ItemStack tridentItemStack, float velocityX, float velocityY, float velocityZ) {
1562+
public static boolean callPlayerRiptideEvent(net.minecraft.world.entity.player.Player player, ItemStack tridentItemStack, float velocityX, float velocityY, float velocityZ) {
15631563
PlayerRiptideEvent event = new PlayerRiptideEvent((Player) player.getBukkitEntity(), CraftItemStack.asCraftMirror(tridentItemStack), new Vector(velocityX, velocityY, velocityZ));
1564-
player.level().getCraftServer().getPluginManager().callEvent(event);
1564+
return event.callEvent();
15651565
}
15661566

15671567
public static BlockShearEntityEvent callBlockShearEntityEvent(Entity animal, org.bukkit.block.Block dispenser, CraftItemStack is, List<ItemStack> drops) { // Paper - custom shear drops

0 commit comments

Comments
 (0)