dropped items merge

This commit is contained in:
2026-09-20 04:57:32 +01:00
parent b17dfd17e8
commit c2528bf55e
@@ -4,10 +4,15 @@ import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.event.player.PlayerPickupItemEvent;
import java.util.List;
import java.util.logging.Level;
public class EntityItem extends Entity {
private static final double MERGE_RADIUS = 5.0D;
private static final double MERGE_RADIUS_SQUARED = MERGE_RADIUS * MERGE_RADIUS;
private static final int MERGE_INTERVAL_TICKS = 10;
public ItemStack itemStack;
private int e;
public int b = 0;
@@ -100,6 +105,13 @@ public class EntityItem extends Entity {
++this.e;
++this.b;
// Merge only settled items. This avoids combining drops while they are still
// being thrown, while keeping large piles from creating excess entities.
if (this.onGround && this.b % MERGE_INTERVAL_TICKS == 0) {
this.mergeNearbyItems();
}
if (this.b >= 6000) {
//Project Poseidon Start
if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) {
@@ -111,6 +123,51 @@ public class EntityItem extends Entity {
}
}
/**
* Merges compatible, grounded item entities within {@link #MERGE_RADIUS} blocks.
* The item count is never allowed to exceed the item's normal stack limit.
*/
private void mergeNearbyItems() {
if (this.dead || !this.itemStack.isStackable() || this.itemStack.count >= this.itemStack.getMaxStackSize()) {
return;
}
List nearbyItems = this.world.a(EntityItem.class, this.boundingBox.b(MERGE_RADIUS, MERGE_RADIUS, MERGE_RADIUS));
for (int i = 0; i < nearbyItems.size() && this.itemStack.count < this.itemStack.getMaxStackSize(); ++i) {
EntityItem nearbyItem = (EntityItem) nearbyItems.get(i);
if (nearbyItem == this || nearbyItem.dead || !nearbyItem.onGround
|| !this.itemStack.doMaterialsMatch(nearbyItem.itemStack)
|| !nearbyItem.itemStack.isStackable()) {
continue;
}
double deltaX = this.locX - nearbyItem.locX;
double deltaY = this.locY - nearbyItem.locY;
double deltaZ = this.locZ - nearbyItem.locZ;
if (deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ > MERGE_RADIUS_SQUARED) {
continue;
}
int transfer = Math.min(this.itemStack.getMaxStackSize() - this.itemStack.count, nearbyItem.itemStack.count);
if (transfer <= 0) {
continue;
}
this.itemStack.count += transfer;
nearbyItem.itemStack.count -= transfer;
// Preserve the stricter expiry and pickup delay when two piles combine.
this.b = Math.max(this.b, nearbyItem.b);
this.pickupDelay = Math.max(this.pickupDelay, nearbyItem.pickupDelay);
if (nearbyItem.itemStack.count <= 0) {
nearbyItem.die();
}
}
}
public boolean f_() {
return this.world.a(this.boundingBox, Material.WATER, this);
}