net/minecraft/world/entity/item

This commit is contained in:
Shane Freeder
2024-12-14 17:57:17 +00:00
parent 822b963d3f
commit 1a214aed6a
4 changed files with 306 additions and 326 deletions

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;
}
}

View File

@@ -1,389 +0,0 @@
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -5,18 +5,6 @@
import java.util.Objects;
import java.util.UUID;
import javax.annotation.Nullable;
-import net.minecraft.core.BlockPos;
-import net.minecraft.nbt.CompoundTag;
-import net.minecraft.network.chat.Component;
-import net.minecraft.network.syncher.EntityDataAccessor;
-import net.minecraft.network.syncher.EntityDataSerializers;
-import net.minecraft.network.syncher.SynchedEntityData;
-import net.minecraft.server.level.ServerLevel;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.tags.ItemTags;
-import net.minecraft.util.Mth;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
@@ -24,7 +12,6 @@
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.entity.SlotAccess;
import net.minecraft.world.entity.TraceableEntity;
-import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Explosion;
@@ -33,6 +20,27 @@
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
+import net.minecraft.core.BlockPos;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.syncher.EntityDataAccessor;
+import net.minecraft.network.syncher.EntityDataSerializers;
+import net.minecraft.network.syncher.SynchedEntityData;
+// CraftBukkit start
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.stats.Stats;
+import net.minecraft.tags.FluidTags;
+import net.minecraft.tags.ItemTags;
+import net.minecraft.util.Mth;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.entity.Player;
+import org.bukkit.event.entity.EntityPickupItemEvent;
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.event.player.PlayerPickupItemEvent;
+// CraftBukkit end
+import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper
public class ItemEntity extends Entity implements TraceableEntity {
@@ -52,6 +60,10 @@
@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(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);
+ // 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.setDeltaMovement(this.random.nextDouble() * 0.2D - 0.1D, 0.2D, this.random.nextDouble() * 0.2D - 0.1D);
+ this.setItem(stack);
+ // 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 @@
@Override
public void tick() {
if (this.getItem().isEmpty()) {
- this.discard();
+ 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 @@
}
}
- 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
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) {
+ f = 1F;
+ } else if (this.onGround()) {
+ // Paper end - Friction API
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 @@
}
}
- 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()) {
+ this.age = 0;
+ return;
+ }
+ // CraftBukkit end
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
}
}
}
+ // Spigot start - copied from above
@Override
+ public void inactiveTick() {
+ // Paper start - remove anti tick skipping measures / wall time - copied from above
+ if (this.pickupDelay > 0 && this.pickupDelay != 32767) {
+ --this.pickupDelay;
+ }
+ if (this.age != -32768) {
+ ++this.age;
+ }
+ // Paper end - remove anti tick skipping measures / wall time - copied from above
+
+ if (!this.level().isClientSide && this.age >= this.despawnRate) { // Spigot // Paper - Alternative item-despawn-rate
+ // CraftBukkit start - fire ItemDespawnEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) {
+ this.age = 0;
+ return;
+ }
+ // CraftBukkit end
+ this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
+ }
+ }
+ // Spigot end
+
+ @Override
public BlockPos getBlockPosBelowThatAffectsMyMovement() {
return this.getOnPos(0.999999F);
}
@@ -229,7 +284,10 @@
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()) {
+ // Paper start - Fix items merging through walls
+ if (this.level().paperConfig().fixes.fixItemsMergingThroughWalls) {
+ if (this.level().clipDirect(this.position(), entityitem.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);
if (this.isRemoved()) {
break;
@@ -251,7 +317,7 @@
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
}
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);
} else {
ItemEntity.merge(other, itemstack1, this, itemstack);
@@ -287,11 +353,16 @@
}
private static void merge(ItemEntity targetEntity, ItemStack targetStack, ItemEntity sourceEntity, ItemStack sourceStack) {
+ // CraftBukkit start
+ if (!CraftEventFactory.callItemMergeEvent(sourceEntity, targetEntity)) {
+ 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);
}
}
@@ -320,12 +391,17 @@
} else if (!this.getItem().canBeHurtBy(source)) {
return false;
} else {
+ // CraftBukkit start
+ if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) {
+ return false;
+ }
+ // CraftBukkit end
this.markHurt();
this.health = (int) ((float) this.health - amount);
this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity());
if (this.health <= 0) {
this.getItem().onDestroyed(this);
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
}
return true;
@@ -339,6 +415,11 @@
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
+ // Paper start - Friction API
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ nbt.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 @@
this.setItem(ItemStack.EMPTY);
}
+ // Paper start - Friction API
+ if (nbt.contains("Paper.FrictionState")) {
+ String fs = nbt.getString("Paper.FrictionState");
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ } catch (Exception ignored) {
+ com.mojang.logging.LogUtils.getLogger().error("Unknown friction state " + fs + " for " + this);
+ }
+ }
+ // 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) {
if (!this.level().isClientSide) {
ItemStack itemstack = this.getItem();
Item item = itemstack.getItem();
int i = itemstack.getCount();
+
+ // CraftBukkit start - fire PlayerPickupItemEvent
+ int canHold = player.getInventory().canHold(itemstack);
+ int remaining = i - 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);
+ this.level().getCraftServer().getPluginManager().callEvent(attemptEvent);
+
+ flyAtPlayer = attemptEvent.getFlyAtPlayer();
+ if (attemptEvent.isCancelled()) {
+ if (flyAtPlayer) {
+ player.take(this, i);
+ }
+
+ return;
+ }
+ }
+ // Paper end - PlayerAttemptPickupItemEvent
+ if (this.pickupDelay <= 0 && canHold > 0) {
+ itemstack.setCount(canHold);
+ // Call legacy event
+ PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((Player) player.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
+ // Paper start
+ if (flyAtPlayer) {
+ player.take(this, i);
+ }
+ // Paper end
+ return;
+ }
+
+ // Call newer event afterwards
+ EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((Player) player.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
+ return;
+ }
+
+ // Update the ItemStack if it was changed in the event
+ ItemStack current = this.getItem();
+ if (!itemstack.equals(current)) {
+ itemstack = current;
+ } else {
+ itemstack.setCount(canHold + remaining); // = i
+ }
+
+ // Possibly < 0; fix here so we do not have to modify code below
+ this.pickupDelay = 0;
+ } else if (this.pickupDelay == 0) {
+ // ensure that the code below isn't triggered if canHold says we can't pick the items up
+ this.pickupDelay = -1;
+ }
+ // CraftBukkit end
+
if (this.pickupDelay == 0 && (this.target == null || this.target.equals(player.getUUID())) && player.getInventory().add(itemstack)) {
+ if (flyAtPlayer) // Paper - PlayerPickupItemEvent
player.take(this, i);
if (itemstack.isEmpty()) {
- this.discard();
+ this.discard(EntityRemoveEvent.Cause.PICKUP); // CraftBukkit - add Bukkit remove cause
itemstack.setCount(i);
}
@@ -438,6 +594,7 @@
public void setItem(ItemStack stack) {
this.getEntityData().set(ItemEntity.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 @@
public void makeFakeItem() {
this.setNeverPickUp();
- this.age = 5999;
+ this.age = this.despawnRate - 1; // Spigot // Paper - Alternative item-despawn-rate
}
public static float getSpin(float f, float f1) {

View File

@@ -1,116 +0,0 @@
--- a/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/net/minecraft/world/entity/item/PrimedTnt.java
@@ -27,6 +27,12 @@
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.portal.TeleportTransition;
+// CraftBukkit start;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.event.entity.ExplosionPrimeEvent;
+// 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 @@
public LivingEntity owner;
private boolean usedPortal;
public float explosionPower;
+ 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);
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);
this.setFuse(80);
@@ -94,10 +101,17 @@
@Override
public void tick() {
+ if (this.level().spigotConfig.maxTntTicksPerTick > 0 && ++this.level().spigotConfig.currentPrimedTnt > this.level().spigotConfig.maxTntTicksPerTick) { return; } // Spigot
this.handlePortal();
this.applyGravity();
this.move(MoverType.SELF, this.getDeltaMovement());
this.applyEffectsFromBlocks();
+ // Paper start - Configurable TNT height nerf
+ if (this.level().paperConfig().fixes.tntEntityHeightNerf.test(v -> this.getY() > v)) {
+ this.discard(EntityRemoveEvent.Cause.OUT_OF_WORLD);
+ return;
+ }
+ // Paper end - Configurable TNT height nerf
this.setDeltaMovement(this.getDeltaMovement().scale(0.98D));
if (this.onGround()) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D));
@@ -107,10 +121,13 @@
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();
if (!this.level().isClientSide) {
this.explode();
}
+ this.discard(EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause
+ // CraftBukkit end
} else {
this.updateInWaterStateAndDoFluidPushing();
if (this.level().isClientSide) {
@@ -118,10 +135,37 @@
}
}
+ // Paper start - Option to prevent TNT from moving in water
+ if (!this.isRemoved() && this.wasTouchingWater && this.level().paperConfig().fixes.preventTntFromMovingInWater) {
+ /*
+ * Author: Jedediah Smith <jedediah@silencegreys.com>
+ */
+ // Send position and velocity updates to nearby players on every tick while the TNT is in water.
+ // This does pretty well at keeping their clients in sync with the server.
+ net.minecraft.server.level.ChunkMap.TrackedEntity ete = ((net.minecraft.server.level.ServerLevel) this.level()).getChunkSource().chunkMap.entityMap.get(this.getId());
+ if (ete != null) {
+ net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket velocityPacket = new net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket(this);
+ net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket positionPacket = net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket.teleport(this.getId(), net.minecraft.world.entity.PositionMoveRotation.of(this), java.util.Set.of(), this.onGround);
+
+ ete.seenBy.stream()
+ .filter(viewer -> (viewer.getPlayer().getX() - this.getX()) * (viewer.getPlayer().getY() - this.getY()) * (viewer.getPlayer().getZ() - this.getZ()) < 16 * 16)
+ .forEach(viewer -> {
+ viewer.send(velocityPacket);
+ viewer.send(positionPacket);
+ });
+ }
+ }
+ // Paper end - Option to prevent TNT from moving in water
}
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
}
@Override
@@ -198,4 +242,11 @@
public final boolean hurtServer(ServerLevel world, DamageSource source, float amount) {
return false;
}
+
+ // Paper start - Option to prevent TNT from moving in water
+ @Override
+ public boolean isPushedByFluid() {
+ return !level().paperConfig().fixes.preventTntFromMovingInWater && super.isPushedByFluid();
+ }
+ // Paper end - Option to prevent TNT from moving in water
}