net/minecraft/world/entity/item

This commit is contained in:
Shane Freeder 2024-12-14 17:57:17 +00:00
parent 822b963d3f
commit 1a214aed6a
No known key found for this signature in database
GPG key ID: A3F61EA5A085289C
4 changed files with 306 additions and 326 deletions

View file

@ -0,0 +1,165 @@
--- a/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -47,8 +_,14 @@
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
+import org.bukkit.event.entity.CreatureSpawnEvent;
import org.slf4j.Logger;
+// CraftBukkit start;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
+
public class FallingBlockEntity extends Entity {
private static final Logger LOGGER = LogUtils.getLogger();
public BlockState blockState = Blocks.SAND.defaultBlockState();
@@ -62,6 +_,7 @@
public CompoundTag blockData;
public boolean forceTickAfterTeleportToDuplicate;
protected static final EntityDataAccessor<BlockPos> DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS);
+ public boolean autoExpire = true; // Paper - Expand FallingBlock API
public FallingBlockEntity(EntityType<? extends FallingBlockEntity> entityType, Level level) {
super(entityType, level);
@@ -80,6 +_,10 @@
}
public static FallingBlockEntity fall(Level level, BlockPos pos, BlockState blockState) {
+ // CraftBukkit start
+ return FallingBlockEntity.fall(level, pos, blockState, CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+ public static FallingBlockEntity fall(Level level, BlockPos pos, BlockState blockState, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
FallingBlockEntity fallingBlockEntity = new FallingBlockEntity(
level,
pos.getX() + 0.5,
@@ -89,6 +_,7 @@
? blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(false))
: blockState
);
+ if (!CraftEventFactory.callEntityChangeBlockEvent(fallingBlockEntity, pos, blockState.getFluidState().createLegacyBlock())) return fallingBlockEntity; // CraftBukkit
level.setBlock(pos, blockState.getFluidState().createLegacyBlock(), 3);
level.addFreshEntity(fallingBlockEntity);
return fallingBlockEntity;
@@ -139,13 +_,22 @@
@Override
public void tick() {
if (this.blockState.isAir()) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
Block block = this.blockState.getBlock();
this.time++;
this.applyGravity();
this.move(MoverType.SELF, this.getDeltaMovement());
this.applyEffectsFromBlocks();
+ // Paper start - Configurable falling blocks height nerf
+ if (this.level().paperConfig().fixes.fallingBlockHeightNerf.test(v -> this.getY() > v)) {
+ if (this.dropItem && this.level() instanceof final ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
+ this.spawnAtLocation(serverLevel, block);
+ }
+ this.discard(EntityRemoveEvent.Cause.OUT_OF_WORLD);
+ return;
+ }
+ // Paper end - Configurable falling blocks height nerf
this.handlePortal();
if (this.level() instanceof ServerLevel serverLevel && (this.isAlive() || this.forceTickAfterTeleportToDuplicate)) {
BlockPos blockPos = this.blockPosition();
@@ -166,12 +_,12 @@
}
if (!this.onGround() && !flag1) {
- if (this.time > 100 && (blockPos.getY() <= this.level().getMinY() || blockPos.getY() > this.level().getMaxY()) || this.time > 600) {
+ if ((this.time > 100 && autoExpire) && (blockPos.getY() <= this.level().getMinY() || blockPos.getY() > this.level().getMaxY()) || (this.time > 600 && autoExpire)) { // Paper - Expand FallingBlock API
if (this.dropItem && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
this.spawnAtLocation(serverLevel, block);
}
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
}
} else {
BlockState blockState = this.level().getBlockState(blockPos);
@@ -189,12 +_,18 @@
this.blockState = this.blockState.setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(true));
}
+ // CraftBukkit start
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockPos, this.blockState)) {
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // SPIGOT-6586 called before the event in previous versions
+ return;
+ }
+ // CraftBukkit end
if (this.level().setBlock(blockPos, this.blockState, 3)) {
((ServerLevel)this.level())
.getChunkSource()
.chunkMap
.broadcast(this, new ClientboundBlockUpdatePacket(blockPos, this.level().getBlockState(blockPos)));
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
if (block instanceof Fallable) {
((Fallable)block).onLand(this.level(), blockPos, this.blockState, blockState, this);
}
@@ -218,19 +_,19 @@
}
}
} else if (this.dropItem && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
this.callOnBrokenAfterFall(block, blockPos);
this.spawnAtLocation(serverLevel, block);
}
} else {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
if (this.dropItem && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
this.callOnBrokenAfterFall(block, blockPos);
this.spawnAtLocation(serverLevel, block);
}
}
} else {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
this.callOnBrokenAfterFall(block, blockPos);
}
}
@@ -290,6 +_,7 @@
}
compound.putBoolean("CancelDrop", this.cancelDrop);
+ if (!autoExpire) {compound.putBoolean("Paper.AutoExpire", false);} // Paper - Expand FallingBlock API
}
@Override
@@ -308,7 +_,7 @@
this.dropItem = compound.getBoolean("DropItem");
}
- if (compound.contains("TileEntityData", 10)) {
+ if (compound.contains("TileEntityData", 10) && !(this.level().paperConfig().entities.spawning.filterBadTileEntityNbtFromFallingBlocks && this.blockState.getBlock() instanceof net.minecraft.world.level.block.GameMasterBlock)) { // Paper - Filter bad block entity nbt data from falling blocks
this.blockData = compound.getCompound("TileEntityData").copy();
}
@@ -316,6 +_,12 @@
if (this.blockState.isAir()) {
this.blockState = Blocks.SAND.defaultBlockState();
}
+
+ // Paper start - Expand FallingBlock API
+ if (compound.contains("Paper.AutoExpire")) {
+ this.autoExpire = compound.getBoolean("Paper.AutoExpire");
+ }
+ // Paper end - Expand FallingBlock API
}
public void setHurtsEntities(float fallDamagePerDistance, int fallDamageMax) {
@@ -372,7 +_,7 @@
ResourceKey<Level> resourceKey1 = this.level().dimension();
boolean flag = (resourceKey1 == Level.END || resourceKey == Level.END) && resourceKey1 != resourceKey;
Entity entity = super.teleport(teleportTransition);
- this.forceTickAfterTeleportToDuplicate = entity != null && flag;
+ this.forceTickAfterTeleportToDuplicate = entity != null && flag && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation; // Paper
return entity;
}
}

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -5,18 +5,6 @@
@@ -3,18 +_,6 @@
import java.util.Objects;
import java.util.UUID;
import javax.annotation.Nullable;
@ -19,7 +19,7 @@
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
@@ -24,7 +12,6 @@
@@ -22,7 +_,6 @@
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.entity.SlotAccess;
import net.minecraft.world.entity.TraceableEntity;
@ -27,7 +27,7 @@
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Explosion;
@@ -33,6 +20,27 @@
@@ -31,6 +_,27 @@
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
@ -54,33 +54,32 @@
+import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper
public class ItemEntity extends Entity implements TraceableEntity {
@@ -52,6 +60,10 @@
private static final EntityDataAccessor<ItemStack> DATA_ITEM = SynchedEntityData.defineId(ItemEntity.class, EntityDataSerializers.ITEM_STACK);
@@ -49,6 +_,9 @@
@Nullable
public UUID target;
public final float bobOffs;
+ // private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
+ public boolean canMobPickup = true; // Paper - Item#canEntityPickup
+ private int despawnRate = -1; // Paper - Alternative item-despawn-rate
+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
public ItemEntity(EntityType<? extends ItemEntity> type, Level world) {
super(type, world);
@@ -61,7 +73,12 @@
public ItemEntity(EntityType<? extends ItemEntity> entityType, Level level) {
super(entityType, level);
@@ -57,7 +_,12 @@
}
public ItemEntity(Level world, double x, double y, double z, ItemStack stack) {
- this(world, x, y, z, stack, world.random.nextDouble() * 0.2D - 0.1D, 0.2D, world.random.nextDouble() * 0.2D - 0.1D);
public ItemEntity(Level level, double posX, double posY, double posZ, ItemStack itemStack) {
- this(level, posX, posY, posZ, itemStack, level.random.nextDouble() * 0.2 - 0.1, 0.2, level.random.nextDouble() * 0.2 - 0.1);
+ // Paper start - Don't use level random in entity constructors (to make them thread-safe)
+ this(EntityType.ITEM, world);
+ this.setPos(x, y, z);
+ this(EntityType.ITEM, level);
+ this.setPos(posX, posY, posZ);
+ this.setDeltaMovement(this.random.nextDouble() * 0.2D - 0.1D, 0.2D, this.random.nextDouble() * 0.2D - 0.1D);
+ this.setItem(stack);
+ this.setItem(itemStack);
+ // Paper end - Don't use level random in entity constructors
}
public ItemEntity(Level world, double x, double y, double z, ItemStack stack, double velocityX, double velocityY, double velocityZ) {
@@ -133,12 +150,14 @@
public ItemEntity(Level level, double posX, double posY, double posZ, ItemStack itemStack, double deltaX, double deltaY, double deltaZ) {
@@ -119,7 +_,7 @@
@Override
public void tick() {
if (this.getItem().isEmpty()) {
@ -88,24 +87,16 @@
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
super.tick();
+ // Paper start - remove anti tick skipping measures / wall time - revert to vanilla
if (this.pickupDelay > 0 && this.pickupDelay != 32767) {
--this.pickupDelay;
}
+ // Paper end - remove anti tick skipping measures / wall time - revert to vanilla
this.xo = this.getX();
this.yo = this.getY();
@@ -162,12 +181,16 @@
@@ -147,11 +_,15 @@
}
}
- if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) {
+ if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { // Paper - Diff on change; ActivationRange immunity
- if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-5F || (this.tickCount + this.getId()) % 4 == 0) {
+ if (!this.onGround() || this.getDeltaMovement().horizontalDistanceSqr() > 1.0E-5F || (this.tickCount + this.getId()) % 4 == 0) { // Paper - Diff on change; ActivationRange immunity
this.move(MoverType.SELF, this.getDeltaMovement());
this.applyEffectsFromBlocks();
float f = 0.98F;
- if (this.onGround()) {
+ // Paper start - Friction API
+ if (frictionState == net.kyori.adventure.util.TriState.FALSE) {
@ -115,24 +106,15 @@
f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F;
}
@@ -188,9 +211,11 @@
this.mergeWithNeighbours();
}
+ // Paper - remove anti tick skipping measures / wall time - revert to vanilla /* CraftBukkit start - moved up
if (this.age != -32768) {
++this.age;
}
+ // CraftBukkit end */
this.hasImpulse |= this.updateInWaterStateAndDoFluidPushing();
if (!this.level().isClientSide) {
@@ -201,14 +226,44 @@
@@ -184,11 +_,42 @@
}
}
- if (!this.level().isClientSide && this.age >= 6000) {
- this.discard();
- }
- }
- }
+ if (!this.level().isClientSide && this.age >= this.despawnRate) { // Spigot // Paper - Alternative item-despawn-rate
+ // CraftBukkit start - fire ItemDespawnEvent
+ if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) {
@ -141,13 +123,12 @@
+ }
+ // CraftBukkit end
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
}
}
}
+ }
+ }
+ }
+
+ // Spigot start - copied from above
@Override
+ @Override
+ public void inactiveTick() {
+ // Paper start - remove anti tick skipping measures / wall time - copied from above
+ if (this.pickupDelay > 0 && this.pickupDelay != 32767) {
@ -170,85 +151,76 @@
+ }
+ // Spigot end
+
+ @Override
@Override
public BlockPos getBlockPosBelowThatAffectsMyMovement() {
return this.getOnPos(0.999999F);
}
@@ -229,7 +284,10 @@
@@ -210,9 +_,18 @@
private void mergeWithNeighbours() {
if (this.isMergable()) {
- List<ItemEntity> list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.5D, 0.0D, 0.5D), (entityitem) -> {
+ // Spigot start
+ double radius = this.level().spigotConfig.itemMerge;
+ List<ItemEntity> list = this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(radius, this.level().paperConfig().entities.behavior.onlyMergeItemsHorizontally ? 0 : radius - 0.5D, radius), (entityitem) -> { // Paper - configuration to only merge items horizontally
+ // Spigot end
return entityitem != this && entityitem.isMergable();
});
Iterator iterator = list.iterator();
@@ -238,6 +296,14 @@
ItemEntity entityitem = (ItemEntity) iterator.next();
if (entityitem.isMergable()) {
+ double radius = this.level().spigotConfig.itemMerge; // Spigot
for (ItemEntity itemEntity : this.level()
- .getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.5, 0.0, 0.5), neighbour -> neighbour != this && neighbour.isMergable())) {
+ .getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(radius, this.level().paperConfig().entities.behavior.onlyMergeItemsHorizontally ? 0 : radius - 0.5D, radius), neighbour -> neighbour != this && neighbour.isMergable())) { // Spigot // Paper - configuration to only merge items horizontally
if (itemEntity.isMergable()) {
+ // Paper start - Fix items merging through walls
+ if (this.level().paperConfig().fixes.fixItemsMergingThroughWalls) {
+ if (this.level().clipDirect(this.position(), entityitem.position(),
+ if (this.level().clipDirect(this.position(), itemEntity.position(),
+ net.minecraft.world.phys.shapes.CollisionContext.of(this)) == net.minecraft.world.phys.HitResult.Type.BLOCK) {
+ continue;
+ }
+ }
+ // Paper end - Fix items merging through walls
this.tryToMerge(entityitem);
this.tryToMerge(itemEntity);
if (this.isRemoved()) {
break;
@@ -251,7 +317,7 @@
@@ -224,14 +_,14 @@
private boolean isMergable() {
ItemStack itemstack = this.getItem();
- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < 6000 && itemstack.getCount() < itemstack.getMaxStackSize();
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && itemstack.getCount() < itemstack.getMaxStackSize(); // Paper - Alternative item-despawn-rate
ItemStack item = this.getItem();
- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < 6000 && item.getCount() < item.getMaxStackSize();
+ return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate
}
private void tryToMerge(ItemEntity other) {
@@ -259,7 +325,7 @@
ItemStack itemstack1 = other.getItem();
if (Objects.equals(this.target, other.target) && ItemEntity.areMergable(itemstack, itemstack1)) {
- if (itemstack1.getCount() < itemstack.getCount()) {
+ if (true || itemstack1.getCount() < itemstack.getCount()) { // Spigot
ItemEntity.merge(this, itemstack, other, itemstack1);
private void tryToMerge(ItemEntity itemEntity) {
ItemStack item = this.getItem();
ItemStack item1 = itemEntity.getItem();
if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) {
- if (item1.getCount() < item.getCount()) {
+ if (true || item1.getCount() < item.getCount()) { // Spigot
merge(this, item, itemEntity, item1);
} else {
ItemEntity.merge(other, itemstack1, this, itemstack);
@@ -287,11 +353,16 @@
merge(itemEntity, item1, this, item);
@@ -257,11 +_,16 @@
}
private static void merge(ItemEntity targetEntity, ItemStack targetStack, ItemEntity sourceEntity, ItemStack sourceStack) {
private static void merge(ItemEntity destinationEntity, ItemStack destinationStack, ItemEntity originEntity, ItemStack originStack) {
+ // CraftBukkit start
+ if (!CraftEventFactory.callItemMergeEvent(sourceEntity, targetEntity)) {
+ if (!CraftEventFactory.callItemMergeEvent(originEntity, destinationEntity)) {
+ return;
+ }
+ // CraftBukkit end
ItemEntity.merge(targetEntity, targetStack, sourceStack);
targetEntity.pickupDelay = Math.max(targetEntity.pickupDelay, sourceEntity.pickupDelay);
targetEntity.age = Math.min(targetEntity.age, sourceEntity.age);
if (sourceStack.isEmpty()) {
- sourceEntity.discard();
+ sourceEntity.discard(EntityRemoveEvent.Cause.MERGE); // CraftBukkit - add Bukkit remove cause);
merge(destinationEntity, destinationStack, originStack);
destinationEntity.pickupDelay = Math.max(destinationEntity.pickupDelay, originEntity.pickupDelay);
destinationEntity.age = Math.min(destinationEntity.age, originEntity.age);
if (originStack.isEmpty()) {
- originEntity.discard();
+ originEntity.discard(EntityRemoveEvent.Cause.MERGE); // CraftBukkit - add Bukkit remove cause
}
}
}
@@ -320,12 +391,17 @@
} else if (!this.getItem().canBeHurtBy(source)) {
@@ -289,12 +_,17 @@
} else if (!this.getItem().canBeHurtBy(damageSource)) {
return false;
} else {
+ // CraftBukkit start
+ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) {
+ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, damageSource, amount)) {
+ return false;
+ }
+ // CraftBukkit end
this.markHurt();
this.health = (int) ((float) this.health - amount);
this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity());
this.health = (int)(this.health - amount);
this.gameEvent(GameEvent.ENTITY_DAMAGE, damageSource.getEntity());
if (this.health <= 0) {
this.getItem().onDestroyed(this);
- this.discard();
@ -256,25 +228,25 @@
}
return true;
@@ -339,6 +415,11 @@
@@ -308,6 +_,11 @@
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
public void addAdditionalSaveData(CompoundTag compound) {
+ // Paper start - Friction API
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ nbt.putString("Paper.FrictionState", this.frictionState.toString());
+ compound.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end - Friction API
nbt.putShort("Health", (short) this.health);
nbt.putShort("Age", (short) this.age);
nbt.putShort("PickupDelay", (short) this.pickupDelay);
@@ -381,23 +462,98 @@
compound.putShort("Health", (short)this.health);
compound.putShort("Age", (short)this.age);
compound.putShort("PickupDelay", (short)this.pickupDelay);
@@ -347,22 +_,95 @@
} else {
this.setItem(ItemStack.EMPTY);
}
+ // Paper start - Friction API
+ if (nbt.contains("Paper.FrictionState")) {
+ String fs = nbt.getString("Paper.FrictionState");
+ if (compound.contains("Paper.FrictionState")) {
+ String fs = compound.getString("Paper.FrictionState");
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ } catch (Exception ignored) {
@ -282,75 +254,72 @@
+ }
+ }
+ // Paper end - Friction API
+
if (this.getItem().isEmpty()) {
- this.discard();
+ this.discard(null); // CraftBukkit - add Bukkit remove cause
}
}
@Override
- public void playerTouch(Player player) {
+ public void playerTouch(net.minecraft.world.entity.player.Player player) {
- public void playerTouch(Player entity) {
+ public void playerTouch(net.minecraft.world.entity.player.Player entity) {
if (!this.level().isClientSide) {
ItemStack itemstack = this.getItem();
Item item = itemstack.getItem();
int i = itemstack.getCount();
+
ItemStack item = this.getItem();
Item item1 = item.getItem();
int count = item.getCount();
+ // CraftBukkit start - fire PlayerPickupItemEvent
+ int canHold = player.getInventory().canHold(itemstack);
+ int remaining = i - canHold;
+ int canHold = entity.getInventory().canHold(item);
+ int remaining = count - canHold;
+ boolean flyAtPlayer = false; // Paper
+
+ // Paper start - PlayerAttemptPickupItemEvent
+ if (this.pickupDelay <= 0) {
+ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
+ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
+ this.level().getCraftServer().getPluginManager().callEvent(attemptEvent);
+
+ flyAtPlayer = attemptEvent.getFlyAtPlayer();
+ if (attemptEvent.isCancelled()) {
+ if (flyAtPlayer) {
+ player.take(this, i);
+ entity.take(this, count);
+ }
+
+ return;
+ }
+ }
+ // Paper end - PlayerAttemptPickupItemEvent
+
+ if (this.pickupDelay <= 0 && canHold > 0) {
+ itemstack.setCount(canHold);
+ item.setCount(canHold);
+ // Call legacy event
+ PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
+ PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
+ playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems());
+ this.level().getCraftServer().getPluginManager().callEvent(playerEvent);
+ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper
+ if (playerEvent.isCancelled()) {
+ itemstack.setCount(i); // SPIGOT-5294 - restore count
+ item.setCount(count); // SPIGOT-5294 - restore count
+ // Paper start
+ if (flyAtPlayer) {
+ player.take(this, i);
+ entity.take(this, count);
+ }
+ // Paper end
+ return;
+ }
+
+ // Call newer event afterwards
+ EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
+ EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((Player) entity.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining);
+ entityEvent.setCancelled(!entityEvent.getEntity().getCanPickupItems());
+ this.level().getCraftServer().getPluginManager().callEvent(entityEvent);
+ if (entityEvent.isCancelled()) {
+ itemstack.setCount(i); // SPIGOT-5294 - restore count
+ item.setCount(count); // SPIGOT-5294 - restore count
+ return;
+ }
+
+ // Update the ItemStack if it was changed in the event
+ ItemStack current = this.getItem();
+ if (!itemstack.equals(current)) {
+ itemstack = current;
+ if (!item.equals(current)) {
+ item = current;
+ } else {
+ itemstack.setCount(canHold + remaining); // = i
+ item.setCount(canHold + remaining); // = i
+ }
+
+ // Possibly < 0; fix here so we do not have to modify code below
@ -360,25 +329,25 @@
+ this.pickupDelay = -1;
+ }
+ // CraftBukkit end
+
if (this.pickupDelay == 0 && (this.target == null || this.target.equals(player.getUUID())) && player.getInventory().add(itemstack)) {
+ // Paper end - PlayerAttemptPickupItemEvent
if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entity.getUUID())) && entity.getInventory().add(item)) {
+ if (flyAtPlayer) // Paper - PlayerPickupItemEvent
player.take(this, i);
if (itemstack.isEmpty()) {
entity.take(this, count);
if (item.isEmpty()) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
itemstack.setCount(i);
item.setCount(count);
}
@@ -438,6 +594,7 @@
@@ -400,6 +_,7 @@
public void setItem(ItemStack stack) {
this.getEntityData().set(ItemEntity.DATA_ITEM, stack);
this.getEntityData().set(DATA_ITEM, stack);
+ this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(stack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate
}
@Override
@@ -492,7 +649,7 @@
@@ -453,7 +_,7 @@
public void makeFakeItem() {
this.setNeverPickUp();
@ -386,4 +355,4 @@
+ this.age = this.despawnRate - 1; // Spigot // Paper - Alternative item-despawn-rate
}
public static float getSpin(float f, float f1) {
public static float getSpin(float age, float bobOffset) {

View file

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/net/minecraft/world/entity/item/PrimedTnt.java
@@ -27,6 +27,12 @@
@@ -27,6 +_,12 @@
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.portal.TeleportTransition;
@ -11,26 +11,26 @@
+// CraftBukkit end
+
public class PrimedTnt extends Entity implements TraceableEntity {
private static final EntityDataAccessor<Integer> DATA_FUSE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.INT);
@@ -51,6 +57,7 @@
private static final EntityDataAccessor<BlockState> DATA_BLOCK_STATE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.BLOCK_STATE);
@@ -50,6 +_,7 @@
public LivingEntity owner;
private boolean usedPortal;
public float explosionPower;
public float explosionPower = 4.0F;
+ public boolean isIncendiary = false; // CraftBukkit - add field
public PrimedTnt(EntityType<? extends PrimedTnt> type, Level world) {
super(type, world);
@@ -61,7 +68,7 @@
public PrimedTnt(Level world, double x, double y, double z, @Nullable LivingEntity igniter) {
this(EntityType.TNT, world);
public PrimedTnt(EntityType<? extends PrimedTnt> entityType, Level level) {
super(entityType, level);
@@ -59,7 +_,7 @@
public PrimedTnt(Level level, double x, double y, double z, @Nullable LivingEntity owner) {
this(EntityType.TNT, level);
this.setPos(x, y, z);
- double d3 = world.random.nextDouble() * 6.2831854820251465D;
+ double d3 = this.random.nextDouble() * 6.2831854820251465D; // Paper - Don't use level random in entity constructors
this.setDeltaMovement(-Math.sin(d3) * 0.02D, 0.20000000298023224D, -Math.cos(d3) * 0.02D);
- double d = level.random.nextDouble() * (float) (Math.PI * 2);
+ double d = this.random.nextDouble() * (float) (Math.PI * 2); // Paper - Don't use level random in entity constructors
this.setDeltaMovement(-Math.sin(d) * 0.02, 0.2F, -Math.cos(d) * 0.02);
this.setFuse(80);
@@ -94,10 +101,17 @@
this.xo = x;
@@ -91,10 +_,17 @@
@Override
public void tick() {
@ -45,16 +45,16 @@
+ return;
+ }
+ // Paper end - Configurable TNT height nerf
this.setDeltaMovement(this.getDeltaMovement().scale(0.98D));
this.setDeltaMovement(this.getDeltaMovement().scale(0.98));
if (this.onGround()) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D));
@@ -107,10 +121,13 @@
this.setDeltaMovement(this.getDeltaMovement().multiply(0.7, -0.5, 0.7));
@@ -103,19 +_,49 @@
int i = this.getFuse() - 1;
this.setFuse(i);
if (i <= 0) {
- this.discard();
+ // CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event
+ // this.discard();
+ //this.discard();
if (!this.level().isClientSide) {
this.explode();
}
@ -63,10 +63,9 @@
} else {
this.updateInWaterStateAndDoFluidPushing();
if (this.level().isClientSide) {
@@ -118,10 +135,37 @@
this.level().addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5, this.getZ(), 0.0, 0.0, 0.0);
}
}
+ // Paper start - Option to prevent TNT from moving in water
+ if (!this.isRemoved() && this.wasTouchingWater && this.level().paperConfig().fixes.preventTntFromMovingInWater) {
+ /*
@ -91,19 +90,28 @@
}
private void explode() {
- this.level().explode(this, Explosion.getDefaultDamageSource(this.level(), this), this.usedPortal ? PrimedTnt.USED_PORTAL_DAMAGE_CALCULATOR : null, this.getX(), this.getY(0.0625D), this.getZ(), this.explosionPower, false, Level.ExplosionInteraction.TNT);
+ // CraftBukkit start
+ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity());
+ if (event.isCancelled()) {
+ return;
+ }
+ this.level().explode(this, Explosion.getDefaultDamageSource(this.level(), this), this.usedPortal ? PrimedTnt.USED_PORTAL_DAMAGE_CALCULATOR : null, this.getX(), this.getY(0.0625D), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.TNT);
+ // CraftBukkit end
+ // Craftbukkit end
this.level()
.explode(
this,
@@ -124,8 +_,8 @@
this.getX(),
this.getY(0.0625),
this.getZ(),
- this.explosionPower,
- false,
+ event.getRadius(), // CraftBukkit
+ event.getFire(), // CraftBukkit
Level.ExplosionInteraction.TNT
);
}
@Override
@@ -198,4 +242,11 @@
public final boolean hurtServer(ServerLevel world, DamageSource source, float amount) {
@@ -200,4 +_,11 @@
public final boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
return false;
}
+

View file

@ -1,162 +0,0 @@
--- a/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -52,6 +52,11 @@
import net.minecraft.world.phys.Vec3;
import org.slf4j.Logger;
+// CraftBukkit start;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+// CraftBukkit end
+
public class FallingBlockEntity extends Entity {
private static final Logger LOGGER = LogUtils.getLogger();
@@ -66,6 +71,7 @@
public CompoundTag blockData;
public boolean forceTickAfterTeleportToDuplicate;
protected static final EntityDataAccessor<BlockPos> DATA_START_POS = SynchedEntityData.defineId(FallingBlockEntity.class, EntityDataSerializers.BLOCK_POS);
+ public boolean autoExpire = true; // Paper - Expand FallingBlock API
public FallingBlockEntity(EntityType<? extends FallingBlockEntity> type, Level world) {
super(type, world);
@@ -87,10 +93,17 @@
}
public static FallingBlockEntity fall(Level world, BlockPos pos, BlockState state) {
- FallingBlockEntity entityfallingblock = new FallingBlockEntity(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, state.hasProperty(BlockStateProperties.WATERLOGGED) ? (BlockState) state.setValue(BlockStateProperties.WATERLOGGED, false) : state);
+ // CraftBukkit start
+ return FallingBlockEntity.fall(world, pos, state, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
- world.setBlock(pos, state.getFluidState().createLegacyBlock(), 3);
- world.addFreshEntity(entityfallingblock);
+ public static FallingBlockEntity fall(Level world, BlockPos blockposition, BlockState iblockdata, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+ // CraftBukkit end
+ FallingBlockEntity entityfallingblock = new FallingBlockEntity(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) ? (BlockState) iblockdata.setValue(BlockStateProperties.WATERLOGGED, false) : iblockdata);
+ if (!CraftEventFactory.callEntityChangeBlockEvent(entityfallingblock, blockposition, iblockdata.getFluidState().createLegacyBlock())) return entityfallingblock; // CraftBukkit
+
+ world.setBlock(blockposition, iblockdata.getFluidState().createLegacyBlock(), 3);
+ world.addFreshEntity(entityfallingblock, spawnReason); // CraftBukkit
return entityfallingblock;
}
@@ -139,7 +152,7 @@
@Override
public void tick() {
if (this.blockState.isAir()) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
Block block = this.blockState.getBlock();
@@ -147,6 +160,16 @@
this.applyGravity();
this.move(MoverType.SELF, this.getDeltaMovement());
this.applyEffectsFromBlocks();
+ // Paper start - Configurable falling blocks height nerf
+ if (this.level().paperConfig().fixes.fallingBlockHeightNerf.test(v -> this.getY() > v)) {
+ if (this.dropItem && this.level() instanceof final ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
+ this.spawnAtLocation(serverLevel, block);
+ }
+
+ this.discard(EntityRemoveEvent.Cause.OUT_OF_WORLD);
+ return;
+ }
+ // Paper end - Configurable falling blocks height nerf
this.handlePortal();
Level world = this.level();
@@ -169,12 +192,12 @@
}
if (!this.onGround() && !flag1) {
- if (this.time > 100 && (blockposition.getY() <= this.level().getMinY() || blockposition.getY() > this.level().getMaxY()) || this.time > 600) {
+ if ((this.time > 100 && autoExpire) && (blockposition.getY() <= this.level().getMinY() || blockposition.getY() > this.level().getMaxY()) || (this.time > 600 && autoExpire)) { // Paper - Expand FallingBlock API
if (this.dropItem && worldserver.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
this.spawnAtLocation(worldserver, (ItemLike) block);
}
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
}
} else {
BlockState iblockdata = this.level().getBlockState(blockposition);
@@ -191,9 +214,15 @@
this.blockState = (BlockState) this.blockState.setValue(BlockStateProperties.WATERLOGGED, true);
}
+ // CraftBukkit start
+ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, this.blockState)) {
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // SPIGOT-6586 called before the event in previous versions
+ return;
+ }
+ // CraftBukkit end
if (this.level().setBlock(blockposition, this.blockState, 3)) {
((ServerLevel) this.level()).getChunkSource().chunkMap.broadcast(this, new ClientboundBlockUpdatePacket(blockposition, this.level().getBlockState(blockposition)));
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
if (block instanceof Fallable) {
((Fallable) block).onLand(this.level(), blockposition, this.blockState, iblockdata, this);
}
@@ -221,19 +250,19 @@
}
}
} else if (this.dropItem && worldserver.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
this.callOnBrokenAfterFall(block, blockposition);
this.spawnAtLocation(worldserver, (ItemLike) block);
}
} else {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DROP); // CraftBukkit - add Bukkit remove cause
if (this.dropItem && worldserver.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
this.callOnBrokenAfterFall(block, blockposition);
this.spawnAtLocation(worldserver, (ItemLike) block);
}
}
} else {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
this.callOnBrokenAfterFall(block, blockposition);
}
}
@@ -310,6 +339,7 @@
}
nbt.putBoolean("CancelDrop", this.cancelDrop);
+ if (!autoExpire) {nbt.putBoolean("Paper.AutoExpire", false);} // Paper - Expand FallingBlock API
}
@Override
@@ -328,7 +358,7 @@
this.dropItem = nbt.getBoolean("DropItem");
}
- if (nbt.contains("TileEntityData", 10)) {
+ if (nbt.contains("TileEntityData", 10) && !(this.level().paperConfig().entities.spawning.filterBadTileEntityNbtFromFallingBlocks && this.blockState.getBlock() instanceof net.minecraft.world.level.block.GameMasterBlock)) { // Paper - Filter bad block entity nbt data from falling blocks
this.blockData = nbt.getCompound("TileEntityData").copy();
}
@@ -337,6 +367,11 @@
this.blockState = Blocks.SAND.defaultBlockState();
}
+ // Paper start - Expand FallingBlock API
+ if (nbt.contains("Paper.AutoExpire")) {
+ this.autoExpire = nbt.getBoolean("Paper.AutoExpire");
+ }
+ // Paper end - Expand FallingBlock API
}
public void setHurtsEntities(float fallHurtAmount, int fallHurtMax) {
@@ -395,7 +430,7 @@
boolean flag = (resourcekey1 == Level.END || resourcekey == Level.END) && resourcekey1 != resourcekey;
Entity entity = super.teleport(teleportTarget);
- this.forceTickAfterTeleportToDuplicate = entity != null && flag;
+ this.forceTickAfterTeleportToDuplicate = entity != null && flag && io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation; // Paper
return entity;
}
}