mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-25 14:00:15 +01:00
Add ItemSpawnEntityEvent and expand EntityPlaceEvent
This commit is contained in:
parent
11c39637de
commit
5ef0ea1ea7
2 changed files with 678 additions and 0 deletions
|
@ -0,0 +1,304 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 20 Jan 2022 10:54:54 -0800
|
||||
Subject: [PATCH] Add ItemSpawnEntityEvent and expand EntityPlaceEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/event/entity/BlockPlaceEntityEvent.java b/src/main/java/io/papermc/paper/event/entity/BlockPlaceEntityEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..7287ebcf3338ca30cc23efa22084cdaefbcad2da
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/entity/BlockPlaceEntityEvent.java
|
||||
@@ -0,0 +1,48 @@
|
||||
+package io.papermc.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.bukkit.block.BlockFace;
|
||||
+import org.bukkit.block.Dispenser;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.Contract;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Called when a block, like a dispenser, places an
|
||||
+ * entity. {@link #getPlayer()} will always be null.
|
||||
+ * @see org.bukkit.event.hanging.HangingPlaceEvent for paintings, item frames, and leashes.
|
||||
+ * @see org.bukkit.event.entity.EntityPlaceEvent for a player-only version with more context
|
||||
+ * @see PlaceEntityEvent to listen to both blocks and players placing entities
|
||||
+ */
|
||||
+public class BlockPlaceEntityEvent extends PlaceEntityEvent {
|
||||
+
|
||||
+ private final Dispenser dispenser;
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ public BlockPlaceEntityEvent(final @NotNull Entity entity, final @NotNull Block block, final @NotNull BlockFace blockFace, final @NotNull ItemStack spawningStack, final @NotNull Dispenser dispenser) {
|
||||
+ super(entity, null, block, blockFace, spawningStack);
|
||||
+ this.dispenser = dispenser;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Get the dispenser responsible for placing the entity.
|
||||
+ *
|
||||
+ * @return a non-snapshot Dispenser
|
||||
+ */
|
||||
+ public @NotNull Dispenser getDispenser() {
|
||||
+ return this.dispenser;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Player will always be null on this event.
|
||||
+ */
|
||||
+ @Override
|
||||
+ @Contract("-> null")
|
||||
+ public @Nullable Player getPlayer() {
|
||||
+ return null;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/event/entity/ItemSpawnEntityEvent.java b/src/main/java/io/papermc/paper/event/entity/ItemSpawnEntityEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6668171113257f5383904ab145da089600630544
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/entity/ItemSpawnEntityEvent.java
|
||||
@@ -0,0 +1,96 @@
|
||||
+package io.papermc.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.bukkit.block.BlockFace;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.entity.EntityEvent;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * When an itemstack causes the spawning of an entity. Most event fires are going to
|
||||
+ * be the through the sub-event {@link org.bukkit.event.entity.EntityPlaceEvent} but this
|
||||
+ * event will also be fired for mob spawn eggs from players and dispensers.
|
||||
+ */
|
||||
+public class ItemSpawnEntityEvent extends EntityEvent implements Cancellable {
|
||||
+
|
||||
+ private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
+
|
||||
+ private final Player player;
|
||||
+ private final Block block;
|
||||
+ private final BlockFace blockFace;
|
||||
+ private final ItemStack spawningStack;
|
||||
+ private boolean cancelled;
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ public ItemSpawnEntityEvent(final @NotNull Entity entity, final @Nullable Player player, final @NotNull Block block, final @NotNull BlockFace blockFace, final @NotNull ItemStack spawningStack) {
|
||||
+ super(entity);
|
||||
+ this.player = player;
|
||||
+ this.block = block;
|
||||
+ this.blockFace = blockFace;
|
||||
+ this.spawningStack = spawningStack;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the player placing the entity (if one is available).
|
||||
+ *
|
||||
+ * @return the player placing the entity
|
||||
+ */
|
||||
+ public @Nullable Player getPlayer() {
|
||||
+ return this.player;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the block that the entity was placed on
|
||||
+ *
|
||||
+ * @return the block that the entity was placed on
|
||||
+ */
|
||||
+ public @NotNull Block getBlock() {
|
||||
+ return this.block;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Returns the face of the block that the entity was placed on
|
||||
+ *
|
||||
+ * @return the face of the block that the entity was placed on
|
||||
+ */
|
||||
+ public @NotNull BlockFace getBlockFace() {
|
||||
+ return this.blockFace;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the itemstack responsible for spawning the entity. Mutating
|
||||
+ * this itemstack has no effect.
|
||||
+ * <p>
|
||||
+ * May return an empty itemstack if the actual stack isn't available.
|
||||
+ *
|
||||
+ * @return the spawning itemstack
|
||||
+ */
|
||||
+ public @NotNull ItemStack getSpawningStack() {
|
||||
+ return this.spawningStack;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return this.cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(final boolean cancel) {
|
||||
+ this.cancelled = cancel;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public @NotNull HandlerList getHandlers() {
|
||||
+ return HANDLER_LIST;
|
||||
+ }
|
||||
+
|
||||
+ public static @NotNull HandlerList getHandlerList() {
|
||||
+ return HANDLER_LIST;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/event/entity/PlaceEntityEvent.java b/src/main/java/io/papermc/paper/event/entity/PlaceEntityEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..bfd7204c71a1ca46df3e5174aef3fe33e59b4ee6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/event/entity/PlaceEntityEvent.java
|
||||
@@ -0,0 +1,28 @@
|
||||
+package io.papermc.paper.event.entity;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+import org.bukkit.block.BlockFace;
|
||||
+import org.bukkit.entity.Entity;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.jetbrains.annotations.ApiStatus;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.jetbrains.annotations.Nullable;
|
||||
+
|
||||
+/**
|
||||
+ * Triggered when an entity is created in the world by "placing" an item
|
||||
+ * on a block from a player or dispenser.
|
||||
+ * <br>
|
||||
+ * Note that this event is currently only fired for these specific placements:
|
||||
+ * armor stands, boats, minecarts, end crystals, mob buckets, and tnt (dispenser only).
|
||||
+ * @see org.bukkit.event.hanging.HangingPlaceEvent for paintings, item frames, and leashes.
|
||||
+ * @see org.bukkit.event.entity.EntityPlaceEvent for a player-only version with more context
|
||||
+ * @see BlockPlaceEntityEvent for a dispener-only version with more context
|
||||
+ */
|
||||
+public abstract class PlaceEntityEvent extends ItemSpawnEntityEvent {
|
||||
+
|
||||
+ @ApiStatus.Internal
|
||||
+ protected PlaceEntityEvent(final @NotNull Entity entity, final @Nullable Player player, final @NotNull Block block, final @NotNull BlockFace blockFace, final @NotNull ItemStack spawningStack) {
|
||||
+ super(entity, player, block, blockFace, spawningStack);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java b/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java
|
||||
index 71d664dd89995f088c47d17b38547d530319470c..645ef8dde4acce134531cb94344d9d84a8ffdc6a 100644
|
||||
--- a/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java
|
||||
+++ b/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java
|
||||
@@ -14,61 +14,34 @@ import org.jetbrains.annotations.Nullable;
|
||||
* Triggered when an entity is created in the world by a player "placing" an item
|
||||
* on a block.
|
||||
* <br>
|
||||
- * Note that this event is currently only fired for four specific placements:
|
||||
- * armor stands, boats, minecarts, and end crystals.
|
||||
+ * Note that this event is currently only fired for these specific placements:
|
||||
+ * armor stands, boats, minecarts, end crystals, and mob buckets.
|
||||
+ * @see org.bukkit.event.hanging.HangingPlaceEvent for paintings, item frames, and leashes.
|
||||
+ * @see io.papermc.paper.event.entity.BlockPlaceEntityEvent for a dispenser-only version
|
||||
+ * @see io.papermc.paper.event.entity.PlaceEntityEvent to listen to both blocks and players placing entities
|
||||
*/
|
||||
-public class EntityPlaceEvent extends EntityEvent implements Cancellable {
|
||||
+public class EntityPlaceEvent extends io.papermc.paper.event.entity.PlaceEntityEvent implements Cancellable { // Paper - move to superclass
|
||||
|
||||
- private static final HandlerList handlers = new HandlerList();
|
||||
- private boolean cancelled;
|
||||
- private final Player player;
|
||||
- private final Block block;
|
||||
- private final BlockFace blockFace;
|
||||
+ // Paper - move to superclass
|
||||
private final EquipmentSlot hand;
|
||||
|
||||
- public EntityPlaceEvent(@NotNull final Entity entity, @Nullable final Player player, @NotNull final Block block, @NotNull final BlockFace blockFace, @NotNull final EquipmentSlot hand) {
|
||||
- super(entity);
|
||||
- this.player = player;
|
||||
- this.block = block;
|
||||
- this.blockFace = blockFace;
|
||||
- this.hand = hand;
|
||||
- }
|
||||
-
|
||||
+ // Paper start - move event to superclass
|
||||
@Deprecated
|
||||
public EntityPlaceEvent(@NotNull final Entity entity, @Nullable final Player player, @NotNull final Block block, @NotNull final BlockFace blockFace) {
|
||||
this(entity, player, block, blockFace, EquipmentSlot.HAND);
|
||||
}
|
||||
|
||||
- /**
|
||||
- * Returns the player placing the entity
|
||||
- *
|
||||
- * @return the player placing the entity
|
||||
- */
|
||||
- @Nullable
|
||||
- public Player getPlayer() {
|
||||
- return player;
|
||||
- }
|
||||
-
|
||||
- /**
|
||||
- * Returns the block that the entity was placed on
|
||||
- *
|
||||
- * @return the block that the entity was placed on
|
||||
- */
|
||||
- @NotNull
|
||||
- public Block getBlock() {
|
||||
- return block;
|
||||
+ @Deprecated
|
||||
+ public EntityPlaceEvent(@NotNull final Entity entity, @Nullable final Player player, @NotNull final Block block, @NotNull final BlockFace blockFace, @NotNull final EquipmentSlot hand) {
|
||||
+ this(entity, player, block, blockFace, hand, org.bukkit.inventory.ItemStack.empty());
|
||||
}
|
||||
|
||||
- /**
|
||||
- * Returns the face of the block that the entity was placed on
|
||||
- *
|
||||
- * @return the face of the block that the entity was placed on
|
||||
- */
|
||||
- @NotNull
|
||||
- public BlockFace getBlockFace() {
|
||||
- return blockFace;
|
||||
+ @org.jetbrains.annotations.ApiStatus.Internal
|
||||
+ public EntityPlaceEvent(final @NotNull Entity entity, final @Nullable Player player, final @NotNull Block block, final @NotNull BlockFace blockFace, final @NotNull EquipmentSlot hand, final @NotNull org.bukkit.inventory.ItemStack spawningStack) {
|
||||
+ super(entity, player, block, blockFace, spawningStack);
|
||||
+ this.hand = hand;
|
||||
}
|
||||
-
|
||||
+ // Paper end
|
||||
/**
|
||||
* Get the hand used to place the entity.
|
||||
*
|
||||
@@ -79,24 +52,5 @@ public class EntityPlaceEvent extends EntityEvent implements Cancellable {
|
||||
return hand;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public boolean isCancelled() {
|
||||
- return cancelled;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void setCancelled(boolean cancel) {
|
||||
- this.cancelled = cancel;
|
||||
- }
|
||||
-
|
||||
- @NotNull
|
||||
- @Override
|
||||
- public HandlerList getHandlers() {
|
||||
- return handlers;
|
||||
- }
|
||||
-
|
||||
- @NotNull
|
||||
- public static HandlerList getHandlerList() {
|
||||
- return handlers;
|
||||
- }
|
||||
+ // Paper - move to superclass
|
||||
}
|
|
@ -0,0 +1,374 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 20 Jan 2022 10:54:45 -0800
|
||||
Subject: [PATCH] Add ItemSpawnEntityEvent and expand EntityPlaceEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
index 6df0db8b4cdab23494ea34236949ece4989110a3..9ebc4e88efcf1ab3130f150a84c3f2c72d18c92c 100644
|
||||
--- a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
+++ b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
|
||||
@@ -90,6 +90,11 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
|
||||
EntityType.createDefaultStackConfig(worldserver, stack, (Player) null).accept(object);
|
||||
((Boat) object).setVariant(this.type);
|
||||
((Boat) object).setYRot(enumdirection.toYRot());
|
||||
+ // Paper start
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEntityEvent(pointer, object, stack).isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (worldserver.addFreshEntity((Entity) object) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink
|
||||
return stack;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..f1a1168d1cff8095eb8fdd6ac445ae8a26161692 100644
|
||||
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -140,7 +140,13 @@ public interface DispenseItemBehavior {
|
||||
}
|
||||
|
||||
try {
|
||||
- entitytypes.spawn(pointer.level(), itemstack1, (Player) null, pointer.pos().relative(enumdirection), MobSpawnType.DISPENSER, enumdirection != Direction.UP, false); // Paper - track changed item in dispense event
|
||||
+ // Paper start
|
||||
+ entitytypes.spawn(pointer.level(), itemstack1, (Player) null, pointer.pos().relative(enumdirection), MobSpawnType.DISPENSER, enumdirection != Direction.UP, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DISPENSE_EGG, entity -> { // Paper - track changed item in dispense event
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemSpawnEntityEvent(pointer.level(), pointer.pos().relative(enumdirection), enumdirection.getOpposite(), null, entity, stack).isCancelled()) {
|
||||
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end
|
||||
} catch (Exception exception) {
|
||||
DispenseItemBehavior.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", pointer.pos(), exception); // CraftBukkit - decompile error
|
||||
return ItemStack.EMPTY;
|
||||
@@ -199,7 +205,16 @@ public interface DispenseItemBehavior {
|
||||
Consumer<ArmorStand> consumer = EntityType.appendDefaultStackConfig((entityarmorstand) -> {
|
||||
entityarmorstand.setYRot(enumdirection.toYRot());
|
||||
}, worldserver, newStack, (Player) null); // Paper - track changed items in the dispense event
|
||||
+ // Paper start
|
||||
+ final java.util.concurrent.atomic.AtomicBoolean cancelled = new java.util.concurrent.atomic.AtomicBoolean(false);
|
||||
+ consumer = consumer.andThen(stand -> {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEntityEvent(pointer, stand, stack).isCancelled()) {
|
||||
+ cancelled.set(true);
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end
|
||||
ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, consumer, blockposition, MobSpawnType.DISPENSER, false, false);
|
||||
+ if (cancelled.get()) shrink = false; // Paper
|
||||
|
||||
if (entityarmorstand != null) {
|
||||
if (shrink) stack.shrink(1); // Paper - actually handle here
|
||||
@@ -456,7 +471,7 @@ public interface DispenseItemBehavior {
|
||||
// CraftBukkit end
|
||||
|
||||
if (dispensiblecontaineritem.emptyContents((Player) null, worldserver, blockposition, (BlockHitResult) null)) {
|
||||
- dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, dispensedItem, blockposition); // Paper - track changed item from dispense event
|
||||
+ dispensiblecontaineritem.checkExtraContent((Player) null, worldserver, dispensedItem, blockposition, null, pointer.state().getValue(DispenserBlock.FACING).getOpposite()); // Paper - track changed item from dispense event
|
||||
// CraftBukkit start - Handle stacked buckets
|
||||
Item item = Items.BUCKET;
|
||||
stack.shrink(1);
|
||||
@@ -708,6 +723,11 @@ public interface DispenseItemBehavior {
|
||||
|
||||
PrimedTnt entitytntprimed = new PrimedTnt(worldserver, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), (LivingEntity) null);
|
||||
// CraftBukkit end
|
||||
+ // Paper start
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEntityEvent(pointer, entitytntprimed, stack).isCancelled()) {
|
||||
+ return stack;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
worldserver.addFreshEntity(entitytntprimed);
|
||||
worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
index a46bf73c608641bf1f00fd55242de71a0f2ee06e..2589b77aee2ffcd2d743d28c3c222f2fcd5798c5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
|
||||
@@ -371,6 +371,13 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
|
||||
@Nullable
|
||||
public T spawn(ServerLevel worldserver, @Nullable ItemStack itemstack, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
+ // Paper start
|
||||
+ return this.spawn(worldserver, itemstack, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, null);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public T spawn(ServerLevel worldserver, @Nullable ItemStack itemstack, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable final Consumer<T> op) {
|
||||
+ // Paper end
|
||||
// CraftBukkit end
|
||||
Consumer<T> consumer; // CraftBukkit - decompile error
|
||||
|
||||
@@ -380,6 +387,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
consumer = (entity) -> {
|
||||
};
|
||||
}
|
||||
+ if (op != null) consumer = consumer.andThen(op); // Paper
|
||||
|
||||
return this.spawn(worldserver, consumer, blockposition, enummobspawn, flag, flag1, spawnReason); // CraftBukkit
|
||||
}
|
||||
@@ -443,6 +451,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
T t0 = this.create(worldserver, consumer, blockposition, enummobspawn, flag, flag1);
|
||||
|
||||
if (t0 != null) {
|
||||
+ if (t0.isRemoved()) return null; // Paper - if consumer removed entity, return null
|
||||
worldserver.addFreshEntityWithPassengers(t0, spawnReason);
|
||||
return !t0.isRemoved() ? t0 : null; // Don't return an entity when CreatureSpawnEvent is canceled
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BoatItem.java b/src/main/java/net/minecraft/world/item/BoatItem.java
|
||||
index eb74d45ad458b80cf8455297c3bc550186adaea3..2bc6df3255b34bfc6d3bb8c9bd9e2bd70af1b049 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BoatItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BoatItem.java
|
||||
@@ -77,7 +77,7 @@ public class BoatItem extends Item {
|
||||
} else {
|
||||
if (!world.isClientSide) {
|
||||
// CraftBukkit start
|
||||
- if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(world, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), user, entityboat, hand).isCancelled()) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(world, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), user, entityboat, hand, itemstack).isCancelled()) { // Paper
|
||||
return InteractionResultHolder.fail(itemstack);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
index 49557d6f22c5725c663a231deab019d4f6fe95fa..d0d6a4525825d30fffce2efa86e77e8492109fea 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/BucketItem.java
|
||||
@@ -107,7 +107,7 @@ public class BucketItem extends Item implements DispensibleContainerItem {
|
||||
BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1;
|
||||
|
||||
if (this.emptyContents(user, world, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit
|
||||
- this.checkExtraContent(user, world, itemstack, blockposition2);
|
||||
+ this.checkExtraContent(user, world, itemstack, blockposition2, hand, movingobjectpositionblock.getDirection()); // Paper
|
||||
if (user instanceof ServerPlayer) {
|
||||
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) user, blockposition2, itemstack);
|
||||
}
|
||||
@@ -135,8 +135,8 @@ public class BucketItem extends Item implements DispensibleContainerItem {
|
||||
return !player.hasInfiniteMaterials() ? new ItemStack(Items.BUCKET) : stack;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public void checkExtraContent(@Nullable Player player, Level world, ItemStack stack, BlockPos pos) {}
|
||||
+ // @Override // Paper - comment out
|
||||
+ // public void checkExtraContent(@Nullable Player player, Level world, ItemStack stack, BlockPos pos) {}
|
||||
|
||||
@Override
|
||||
public boolean emptyContents(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult hitResult) {
|
||||
diff --git a/src/main/java/net/minecraft/world/item/DispensibleContainerItem.java b/src/main/java/net/minecraft/world/item/DispensibleContainerItem.java
|
||||
index 0ca0e2a0a5f63939bd30de22a55806152a5a7698..67f3bc5a88e23bb60e6b300cfa0a7c85fa3ba2d2 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/DispensibleContainerItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/DispensibleContainerItem.java
|
||||
@@ -7,8 +7,13 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
public interface DispensibleContainerItem {
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
|
||||
default void checkExtraContent(@Nullable Player player, Level world, ItemStack stack, BlockPos pos) {
|
||||
}
|
||||
+ // Paper start
|
||||
+ default void checkExtraContent(@Nullable Player player, Level world, ItemStack stack, BlockPos pos, @Nullable net.minecraft.world.InteractionHand hand, @Nullable net.minecraft.core.Direction direction) {
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
boolean emptyContents(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult hitResult);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/item/MobBucketItem.java b/src/main/java/net/minecraft/world/item/MobBucketItem.java
|
||||
index dbbc7dd46484b3434ed3ef9bf5ef7ca7774f0d56..ad62f4fdf9aea0fed5c4953215f05fc048440bf8 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/MobBucketItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/MobBucketItem.java
|
||||
@@ -35,9 +35,9 @@ public class MobBucketItem extends BucketItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void checkExtraContent(@Nullable Player player, Level world, ItemStack stack, BlockPos pos) {
|
||||
+ public void checkExtraContent(@Nullable Player player, Level world, ItemStack stack, BlockPos pos, @Nullable net.minecraft.world.InteractionHand hand, @Nullable net.minecraft.core.Direction direction) { // Paper - add parameters
|
||||
if (world instanceof ServerLevel) {
|
||||
- this.spawn((ServerLevel)world, stack, pos);
|
||||
+ this.spawn((ServerLevel)world, stack, pos, player, hand, direction); // Paper - add parameters
|
||||
world.gameEvent(player, GameEvent.ENTITY_PLACE, pos);
|
||||
}
|
||||
}
|
||||
@@ -47,8 +47,26 @@ public class MobBucketItem extends BucketItem {
|
||||
world.playSound(player, pos, this.emptySound, SoundSource.NEUTRAL, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
|
||||
private void spawn(ServerLevel world, ItemStack stack, BlockPos pos) {
|
||||
- if (this.type.spawn(world, stack, null, pos, MobSpawnType.BUCKET, true, false) instanceof Bucketable bucketable) {
|
||||
+ // Paper start
|
||||
+ this.spawn(world, stack, pos, null, null, null);
|
||||
+ }
|
||||
+ private void spawn(ServerLevel world, ItemStack stack, BlockPos pos, @Nullable Player player, @Nullable net.minecraft.world.InteractionHand hand, @Nullable net.minecraft.core.Direction direction) {
|
||||
+ if (this.type.spawn(world, stack, (Player)null, pos, MobSpawnType.BUCKET, true, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG, entity1 -> {
|
||||
+ if (direction != null) {
|
||||
+ if (hand == null) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEntityEvent(world, pos, direction, entity1, stack).isCancelled()) {
|
||||
+ entity1.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(world, pos, direction, player, entity1, hand, stack).isCancelled()) {
|
||||
+ entity1.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }) instanceof Bucketable bucketable) {
|
||||
+ // Paper end
|
||||
CustomData customData = stack.getOrDefault(DataComponents.BUCKET_ENTITY_DATA, CustomData.EMPTY);
|
||||
bucketable.loadFromBucketTag(customData.copyTag());
|
||||
bucketable.setFromBucket(true);
|
||||
diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.java
|
||||
index 9cea8da84f39bb3f687139ef213ccea358724dee..a6704f39599164dd38c2a92999b7bb72b6e936b5 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java
|
||||
@@ -66,7 +66,7 @@ public class SpawnEggItem extends Item {
|
||||
Direction enumdirection = context.getClickedFace();
|
||||
BlockState iblockdata = world.getBlockState(blockposition);
|
||||
BlockEntity tileentity = world.getBlockEntity(blockposition);
|
||||
- EntityType entitytypes;
|
||||
+ EntityType<?> entitytypes; // Paper - fixme move to mc dev fixes
|
||||
|
||||
if (tileentity instanceof Spawner) {
|
||||
if (world.paperConfig().entities.spawning.disableMobSpawnerSpawnEggTransformation) return InteractionResult.FAIL; // Paper - Allow disabling mob spawner spawn egg transformation
|
||||
@@ -89,7 +89,13 @@ public class SpawnEggItem extends Item {
|
||||
}
|
||||
|
||||
entitytypes = this.getType(itemstack);
|
||||
- if (entitytypes.spawn((ServerLevel) world, itemstack, context.getPlayer(), blockposition1, MobSpawnType.SPAWN_EGG, true, !Objects.equals(blockposition, blockposition1) && enumdirection == Direction.UP) != null) {
|
||||
+ // Paper start
|
||||
+ if (entitytypes.spawn((ServerLevel) world, itemstack, context.getPlayer(), blockposition1, MobSpawnType.SPAWN_EGG, true, !Objects.equals(blockposition, blockposition1) && enumdirection == Direction.UP, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG, entity -> {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemSpawnEntityEvent(context, entity).isCancelled()) {
|
||||
+ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ }
|
||||
+ }) != null) {
|
||||
+ // Paper end
|
||||
itemstack.shrink(1);
|
||||
world.gameEvent((Entity) context.getPlayer(), (Holder) GameEvent.ENTITY_PLACE, blockposition);
|
||||
}
|
||||
@@ -115,7 +121,13 @@ public class SpawnEggItem extends Item {
|
||||
return InteractionResultHolder.pass(itemstack);
|
||||
} else if (world.mayInteract(user, blockposition) && user.mayUseItemAt(blockposition, movingobjectpositionblock.getDirection(), itemstack)) {
|
||||
EntityType<?> entitytypes = this.getType(itemstack);
|
||||
- Entity entity = entitytypes.spawn((ServerLevel) world, itemstack, user, blockposition, MobSpawnType.SPAWN_EGG, false, false);
|
||||
+ // Paper start
|
||||
+ Entity entity = entitytypes.spawn((ServerLevel) world, itemstack, user, blockposition, MobSpawnType.SPAWN_EGG, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG, e -> {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemSpawnEntityEvent(world, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), user, e, itemstack).isCancelled()) {
|
||||
+ e.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end
|
||||
|
||||
if (entity == null) {
|
||||
return InteractionResultHolder.pass(itemstack);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
index 34b91eff3190848bae38b20e1d956ece497b1473..61c05182fa73f0b2f2c9d64d6fcc138929277309 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
|
||||
@@ -479,19 +479,56 @@ public class CraftEventFactory {
|
||||
}
|
||||
|
||||
public static EntityPlaceEvent callEntityPlaceEvent(UseOnContext itemactioncontext, Entity entity) {
|
||||
- return CraftEventFactory.callEntityPlaceEvent(itemactioncontext.getLevel(), itemactioncontext.getClickedPos(), itemactioncontext.getClickedFace(), itemactioncontext.getPlayer(), entity, itemactioncontext.getHand());
|
||||
+ return CraftEventFactory.callEntityPlaceEvent(itemactioncontext.getLevel(), itemactioncontext.getClickedPos(), itemactioncontext.getClickedFace(), itemactioncontext.getPlayer(), entity, itemactioncontext.getHand(), itemactioncontext.getItemInHand()); // Paper
|
||||
}
|
||||
|
||||
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - use #callEntityPlaceEvent with spawningStack parameter
|
||||
public static EntityPlaceEvent callEntityPlaceEvent(Level world, BlockPos clickPosition, Direction clickedFace, net.minecraft.world.entity.player.Player human, Entity entity, InteractionHand enumhand) {
|
||||
+ // Paper start
|
||||
+ return CraftEventFactory.callEntityPlaceEvent(world, clickPosition, clickedFace, human, entity, enumhand, ItemStack.EMPTY);
|
||||
+ }
|
||||
+
|
||||
+ public static EntityPlaceEvent callEntityPlaceEvent(final Level world, final BlockPos clickPosition, final Direction clickedFace, @Nullable final net.minecraft.world.entity.player.Player human, final Entity entity, final InteractionHand hand, final ItemStack spawningStack) {
|
||||
+ // Paper end
|
||||
Player who = (human == null) ? null : (Player) human.getBukkitEntity();
|
||||
org.bukkit.block.Block blockClicked = CraftBlock.at(world, clickPosition);
|
||||
org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(clickedFace);
|
||||
|
||||
- EntityPlaceEvent event = new EntityPlaceEvent(entity.getBukkitEntity(), who, blockClicked, blockFace, CraftEquipmentSlot.getHand(enumhand));
|
||||
+ final EntityPlaceEvent event = new EntityPlaceEvent(entity.getBukkitEntity(), who, blockClicked, blockFace, CraftEquipmentSlot.getHand(hand), spawningStack.asBukkitCopy()); // Paper
|
||||
entity.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
|
||||
return event;
|
||||
}
|
||||
+ // Paper start - various spawn entity events
|
||||
+ public static io.papermc.paper.event.entity.ItemSpawnEntityEvent callItemSpawnEntityEvent(final UseOnContext useOnContext, final Entity entity) {
|
||||
+ return CraftEventFactory.callItemSpawnEntityEvent(useOnContext.getLevel(), useOnContext.getClickedPos(), useOnContext.getClickedFace(), useOnContext.getPlayer(), entity, useOnContext.getItemInHand());
|
||||
+ }
|
||||
+
|
||||
+ public static io.papermc.paper.event.entity.ItemSpawnEntityEvent callItemSpawnEntityEvent(final Level world, final BlockPos clickPosition, final Direction clickedFace, @Nullable final net.minecraft.world.entity.player.Player human, final Entity entity, final ItemStack spawningStack) {
|
||||
+ final Player who = (human == null) ? null : (Player) human.getBukkitEntity();
|
||||
+ final Block blockClicked = CraftBlock.at(world, clickPosition);
|
||||
+ final BlockFace blockFace = CraftBlock.notchToBlockFace(clickedFace);
|
||||
+
|
||||
+ final io.papermc.paper.event.entity.ItemSpawnEntityEvent event = new io.papermc.paper.event.entity.ItemSpawnEntityEvent(entity.getBukkitEntity(), who, blockClicked, blockFace, CraftItemStack.asBukkitCopy(spawningStack));
|
||||
+ event.callEvent();
|
||||
+ return event;
|
||||
+ }
|
||||
+
|
||||
+ public static io.papermc.paper.event.entity.BlockPlaceEntityEvent callBlockPlaceEntityEvent(final net.minecraft.core.dispenser.BlockSource pointer, final Entity entity, final ItemStack spawningStack) {
|
||||
+ final Direction direction = pointer.state().getValue(net.minecraft.world.level.block.DispenserBlock.FACING);
|
||||
+ return callBlockPlaceEntityEvent(pointer.level(), pointer.pos().relative(direction), direction.getOpposite(), entity, spawningStack);
|
||||
+ }
|
||||
+
|
||||
+ public static io.papermc.paper.event.entity.BlockPlaceEntityEvent callBlockPlaceEntityEvent(final Level world, final BlockPos clickedPosition, final Direction clickedFace, final Entity entity, final ItemStack spawningStack) {
|
||||
+ final Block blockClicked = CraftBlock.at(world, clickedPosition);
|
||||
+ final BlockFace blockFace = CraftBlock.notchToBlockFace(clickedFace);
|
||||
+ final org.bukkit.block.Dispenser dispenser = (org.bukkit.block.Dispenser) CraftBlockStates.getBlockState(CraftBlock.at(world, clickedPosition.relative(clickedFace)));
|
||||
+
|
||||
+ final io.papermc.paper.event.entity.BlockPlaceEntityEvent event = new io.papermc.paper.event.entity.BlockPlaceEntityEvent(entity.getBukkitEntity(), blockClicked, blockFace, CraftItemStack.asBukkitCopy(spawningStack), dispenser);
|
||||
+ event.callEvent();
|
||||
+ return event;
|
||||
+ }
|
||||
+ // Paper end - various spawn entity events
|
||||
|
||||
/**
|
||||
* Bucket methods
|
||||
diff --git a/src/test/java/io/papermc/paper/block/DispensibleContainerItemExtraContentsOverrideTest.java b/src/test/java/io/papermc/paper/block/DispensibleContainerItemExtraContentsOverrideTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b1e599a6802e823f94c7a8506a1cea2486acc54c
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/block/DispensibleContainerItemExtraContentsOverrideTest.java
|
||||
@@ -0,0 +1,50 @@
|
||||
+package io.papermc.paper.block;
|
||||
+
|
||||
+import io.github.classgraph.ClassGraph;
|
||||
+import io.github.classgraph.ClassInfo;
|
||||
+import io.github.classgraph.ClassInfoList;
|
||||
+import io.github.classgraph.MethodInfo;
|
||||
+import io.github.classgraph.MethodInfoList;
|
||||
+import io.github.classgraph.MethodParameterInfo;
|
||||
+import io.github.classgraph.ScanResult;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import java.util.stream.Stream;
|
||||
+import net.minecraft.world.item.DispensibleContainerItem;
|
||||
+import org.junit.jupiter.params.ParameterizedTest;
|
||||
+import org.junit.jupiter.params.provider.MethodSource;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+
|
||||
+class DispensibleContainerItemExtraContentsOverrideTest {
|
||||
+
|
||||
+ public static Stream<ClassInfo> parameters() {
|
||||
+ final List<ClassInfo> classInfo = new ArrayList<>();
|
||||
+ try (final ScanResult scanResult = new ClassGraph()
|
||||
+ .enableClassInfo()
|
||||
+ .enableMethodInfo()
|
||||
+ .whitelistPackages("net.minecraft")
|
||||
+ .scan()
|
||||
+ ) {
|
||||
+ final ClassInfoList classesImplementing = scanResult.getClassesImplementing(DispensibleContainerItem.class.getName());
|
||||
+ for (final ClassInfo info : classesImplementing) {
|
||||
+ if (info.hasDeclaredMethod("checkExtraContent")) {
|
||||
+ classInfo.add(info);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return classInfo.stream();
|
||||
+ }
|
||||
+
|
||||
+ @ParameterizedTest
|
||||
+ @MethodSource("parameters")
|
||||
+ public void checkCheckExtraContentOverride(final ClassInfo implementsDispensibleContainerItem) {
|
||||
+ final MethodInfoList checkExtraContent = implementsDispensibleContainerItem.getDeclaredMethodInfo("checkExtraContent");
|
||||
+ assertEquals(1, checkExtraContent.size(), implementsDispensibleContainerItem.getName() + " has multiple checkExtraContent methods");
|
||||
+ final MethodInfo next = checkExtraContent.iterator().next();
|
||||
+ final MethodParameterInfo[] parameterInfo = next.getParameterInfo();
|
||||
+ assertEquals(6, parameterInfo.length, implementsDispensibleContainerItem.getName() + " doesn't have 6 params for checkExtraContent");
|
||||
+ assertEquals("InteractionHand", parameterInfo[parameterInfo.length - 2].getTypeDescriptor().toStringWithSimpleNames(), implementsDispensibleContainerItem.getName() + " needs to change its override of checkExtraContent");
|
||||
+ assertEquals("Direction", parameterInfo[parameterInfo.length - 1].getTypeDescriptor().toStringWithSimpleNames(), implementsDispensibleContainerItem.getName() + " needs to change its override of checkExtraContent");
|
||||
+ }
|
||||
+}
|
Loading…
Reference in a new issue