Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

/**
* Called when a block, like a dispenser, places an
* entity. {@link #getPlayer()} will always be {@code 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
*/
@NullMarked
public class BlockPlaceEntityEvent extends PlaceEntityEvent {

private final Dispenser dispenser;

@ApiStatus.Internal
public BlockPlaceEntityEvent(final Entity entity, final Block block, final BlockFace blockFace, final ItemStack spawningStack, final 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 Dispenser getDispenser() {
return this.dispenser;
}

/**
* Player will always be null on this event.
*/
@Override
@Contract("-> null")
public @Nullable Player getPlayer() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
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.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

/**
* When an item 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.
*/
@NullMarked
public class ItemSpawnEntityEvent extends EntityEvent implements Cancellable {

private static final HandlerList HANDLER_LIST = new HandlerList();

private final @Nullable Player player;
private final Block block;
private final BlockFace blockFace;
private final ItemStack spawningStack;
private boolean cancelled;

@ApiStatus.Internal
public ItemSpawnEntityEvent(final Entity entity, final @Nullable Player player, final Block block, final BlockFace blockFace, final 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 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 BlockFace getBlockFace() {
return this.blockFace;
}

/**
* Gets the item responsible for spawning the entity. Mutating
* this item has no effect.
* <p>
* May return an empty item if the actual stack isn't available.
*
* @return the spawning item
*/
public ItemStack getSpawningStack() {
return this.spawningStack;
}

@Override
public boolean isCancelled() {
return this.cancelled;
}

@Override
public void setCancelled(final boolean cancel) {
this.cancelled = cancel;
}

@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}

public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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.jspecify.annotations.NullMarked;
import org.jspecify.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 dispenser-only version with more context
*/
@NullMarked
public abstract class PlaceEntityEvent extends ItemSpawnEntityEvent {

@ApiStatus.Internal
protected PlaceEntityEvent(final Entity entity, final @Nullable Player player, final Block block, final BlockFace blockFace, final ItemStack spawningStack) {
super(entity, player, block, blockFace, spawningStack);
}
}
Original file line number Diff line number Diff line change
@@ -1,107 +1,77 @@
package org.bukkit.event.entity;

import io.papermc.paper.event.entity.PlaceEntityEvent;
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.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.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 {
@NullMarked
public class EntityPlaceEvent extends PlaceEntityEvent {

private static final HandlerList HANDLER_LIST = new HandlerList();

private final Player player;
private final Block block;
private final BlockFace blockFace;
private final EquipmentSlot hand;

private boolean cancelled;

@ApiStatus.Internal
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;
public EntityPlaceEvent(
final Entity entity,
final @Nullable Player player,
final Block block,
final BlockFace blockFace,
final EquipmentSlot hand,
final ItemStack spawningStack
) {
super(entity, player, block, blockFace, spawningStack);
this.hand = hand;
}

@ApiStatus.Internal
@Deprecated(since = "1.19.2", forRemoval = true)
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 this.player;
@Override
public @Nullable Player getPlayer() {
return super.getPlayer();
}

/**
* Returns the block that the entity was placed on
*
* @return the block that the entity was placed on
*/
@NotNull
@Override
public Block getBlock() {
return this.block;
return super.getBlock();
}

/**
* 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
@Override
public BlockFace getBlockFace() {
return this.blockFace;
return super.getBlockFace();
}

/**
* Get the hand used to place the entity.
*
* @return the hand
*/
@NotNull
public EquipmentSlot getHand() {
return this.hand;
}

@Override
public boolean isCancelled() {
return this.cancelled;
return super.isCancelled();
}

@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}

@NotNull
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}

@NotNull
public static HandlerList getHandlerList() {
return HANDLER_LIST;
public void setCancelled(final boolean cancel) {
super.setCancelled(cancel);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ index c2363cfa5e93942fe837efd9f39478698f6d1a98..2dfd412344a0e57f25a08d9c65656a13
scopedCollector.forChild(entity.problemPath()), entity.registryAccess()
);
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 3cf2378a2ccf117fab9fc6fc60fcb0ecdf638d45..abccad13c2bb3a33e98ad8eb6d7f08c0ef021811 100644
index da522a51978b3c0f67a533ab2085b3f499134dd1..7f7e2f856550737eb9dfbaf1cdb3ee2f655fc674 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -1615,7 +1615,18 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@@ -1621,7 +1621,18 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
}

public static Stream<Entity> loadEntitiesRecursive(ValueInput.ValueInputList input, Level level, EntitySpawnReason spawnReason) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- a/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
+++ b/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
@@ -41,13 +_,36 @@
@@ -41,13 +_,41 @@
d4 = 0.0;
}

Expand Down Expand Up @@ -36,6 +36,11 @@
abstractBoat.setYRot(direction.toYRot());
- serverLevel.addFreshEntity(abstractBoat);
- item.shrink(1);
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEntityEvent(blockSource, abstractBoat, item).isCancelled()) {
+ return item;
+ }
+ // Paper end
+ if (serverLevel.addFreshEntity(abstractBoat) && shrink) item.shrink(1); // Paper - if entity add was successful and supposed to shrink
}

Expand Down
Loading
Loading