Fix empty shulker stacking behavior

This commit is contained in:
NotAlexNoyle committed 2025-12-09 15:14:43 -05:00
1 parent 437c5c95ce
commit f1089443db
7 files changed
+222 -135

No files matched your search

@@ -1,15 +1,11 @@
package me.barny1094875.shulkerstackingog.Listeners;
import me.barny1094875.shulkerstackingog.ShulkerStacking_OG;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import me.barny1094875.shulkerstackingog.ShulkerBoxHelpers.ShulkerBoxUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public class ShulkerBoxHopperHandler implements Listener {
@@ -19,72 +15,44 @@ public class ShulkerBoxHopperHandler implements Listener {
ItemStack eventItem = event.getItem();
Inventory eventDestination = event.getDestination();
Inventory eventSource = event.getSource();
// if the item is a shulker box
if (eventItem.getType().toString().contains("SHULKER_BOX")) {
if (!ShulkerBoxUtils.isEmptyShulkerBox(eventItem)) {
// check that the shulker box is empty
BlockStateMeta shulkerMeta = (BlockStateMeta) eventItem.getItemMeta();
ShulkerBox shulker = (ShulkerBox) shulkerMeta.getBlockState();
if (!shulker.getInventory().isEmpty()) {
return;
return;
}
event.setCancelled(true);
int toMove = eventItem.getAmount();
for (int i = 0; i < eventSource.getSize() && toMove > 0; i++) {
ItemStack sourceItem = eventSource.getItem(i);
if (!ShulkerBoxUtils.isEmptyShulkerBox(sourceItem)) {
continue;
}
// cancel the event so that I can guarantee where the item will be
event.setCancelled(true);
// item is always in eventSource now
if (!sourceItem.getType().equals(eventItem.getType())) {
Material shulkerType = eventItem.getType();
// loop through the destination to see if there is a shulker box stack to add to
for (int i = 0; i < eventDestination.getSize(); i++) {
ItemStack destinationItem = eventDestination.getItem(i);
if (destinationItem == null) {
continue;
}
// if the item is the right kind of shulker box
if (destinationItem.getType().equals(shulkerType)) {
// check that the shulker boxes are emtpy
BlockStateMeta destinationShulkerMeta = (BlockStateMeta) destinationItem.getItemMeta();
ShulkerBox destinationShulker = (ShulkerBox) destinationShulkerMeta.getBlockState();
if (!destinationShulker.getInventory().isEmpty()) {
continue;
}
// check that the item stack is not full
if (destinationItem.getAmount() > 63) {
continue;
}
destinationItem.setAmount(destinationItem.getAmount() + 1);
Bukkit.getScheduler().runTaskLater(ShulkerStacking_OG.getPlugin(), () -> {
eventItem.setAmount(eventItem.getAmount() - 1);
}, 1);
return;
}
continue;
}
// if no shulker box was found, try to put it in the first empty slot
if (eventDestination.addItem(eventItem).isEmpty()) {
int moveAmount = Math.min(sourceItem.getAmount(), toMove);
int remaining = ShulkerBoxUtils.mergeIntoExistingStacks(eventDestination, eventItem, moveAmount);
remaining = ShulkerBoxUtils.fillEmptySlots(eventDestination, eventItem, remaining);
Bukkit.getScheduler().runTaskLater(ShulkerStacking_OG.getPlugin(), () -> {
int moved = moveAmount - remaining;
if (moved > 0) {
eventItem.setAmount(eventItem.getAmount() - 1);
sourceItem.setAmount(sourceItem.getAmount() - moved);
toMove -= moved;
if (sourceItem.getAmount() <= 0) {
}, 1);
eventSource.setItem(i, null);
}
}
@@ -0,0 +1,55 @@
package me.barny1094875.shulkerstackingog.Listeners;
import me.barny1094875.shulkerstackingog.ShulkerBoxHelpers.ShulkerBoxUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ItemMergeEvent;
import org.bukkit.inventory.ItemStack;
public class ShulkerBoxMergeHandler implements Listener {
@EventHandler
public void onItemMerge(ItemMergeEvent event) {
ItemStack target = event.getTarget().getItemStack();
ItemStack source = event.getEntity().getItemStack();
if (!ShulkerBoxUtils.isEmptyShulkerBox(target) || !ShulkerBoxUtils.isEmptyShulkerBox(source)) {
return;
}
if (!target.getType().equals(source.getType())) {
return;
}
event.setCancelled(true);
int space = 64 - target.getAmount();
if (space <= 0) {
return;
}
int moved = Math.min(space, source.getAmount());
target.setAmount(target.getAmount() + moved);
int remaining = source.getAmount() - moved;
if (remaining <= 0) {
event.getEntity().remove();
} else {
source.setAmount(remaining);
event.getEntity().setItemStack(source);
}
}
}
@@ -1,6 +1,6 @@
package me.barny1094875.shulkerstackingog.Listeners;
import org.bukkit.block.ShulkerBox;
import me.barny1094875.shulkerstackingog.ShulkerBoxHelpers.ShulkerBoxUtils;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -8,7 +8,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public class ShulkerBoxPickupHandler implements Listener {
@@ -16,88 +15,40 @@ public class ShulkerBoxPickupHandler implements Listener {
public void shulkerBoxStacking(EntityPickupItemEvent event) {
ItemStack item = event.getItem().getItemStack();
if (!event.getEntity().getType().equals(EntityType.PLAYER)) {
return;
}
Player player = (Player) event.getEntity();
Inventory playerInventory = player.getInventory();
if (item.getType().toString().contains("SHULKER_BOX")) {
if (!ShulkerBoxUtils.isEmptyShulkerBox(item)) {
BlockStateMeta shulker1Meta = (BlockStateMeta) item.getItemMeta();
ShulkerBox shulker1 = (ShulkerBox) shulker1Meta.getBlockState();
// check the inventory of the ground item shulker
if (shulker1.getInventory().isEmpty()) {
// check for shulker box stacks to add to
for (int i = 0; i < playerInventory.getSize(); i++) {
ItemStack inventoryItem = playerInventory.getItem(i);
if (inventoryItem == null) {
continue;
}
if (inventoryItem.getType().equals(item.getType())) {
BlockStateMeta shulker2Meta = (BlockStateMeta) inventoryItem.getItemMeta();
ShulkerBox shulker2 = (ShulkerBox) shulker2Meta.getBlockState();
// check the inventory of the inventory shulker
if (shulker2.getInventory().isEmpty()) {
if (inventoryItem.getAmount() + item.getAmount() <= 64) {
inventoryItem.setAmount(inventoryItem.getAmount() + item.getAmount());
event.getItem().setHealth(-1);
event.setCancelled(true);
return;
}
if (inventoryItem.getAmount() <= 64) {
item.setAmount((item.getAmount() + inventoryItem.getAmount()) - 64);
if (item.getAmount() <= 0) {
event.getItem().setHealth(-1);
return;
}
event.getItem().setItemStack(item);
inventoryItem.setAmount(64);
event.setCancelled(true);
}
}
}
}
// look for air gaps to add the shulkers to
for (int i = 0; i < playerInventory.getSize(); i++) {
ItemStack inventoryItem = playerInventory.getItem(i);
if (inventoryItem == null) {
playerInventory.setItem(i, item);
event.getItem().setHealth(-1);
event.setCancelled(true);
return;
}
}
}
return;
}
event.setCancelled(true);
Player player = (Player) event.getEntity();
Inventory playerInventory = player.getInventory();
int remaining = item.getAmount();
remaining = ShulkerBoxUtils.mergeIntoExistingStacks(playerInventory, item, remaining);
remaining = ShulkerBoxUtils.fillEmptySlots(playerInventory, item, remaining);
if (remaining <= 0) {
event.getItem().remove();
player.updateInventory();
return;
}
ItemStack remainingItem = new ItemStack(item.getType(), remaining);
event.getItem().setItemStack(remainingItem);
player.updateInventory();
}
}
@@ -1,5 +1,6 @@
package me.barny1094875.shulkerstackingog.ShulkerBoxHelpers;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
@@ -27,7 +28,7 @@ public class NormalLeftClick {
// add the shulker itemStacks together
event.getCurrentItem()
.setAmount(event.getCursor().getAmount() + event.getCurrentItem().getAmount());
event.getWhoClicked().getItemOnCursor().setAmount(0);
event.getWhoClicked().setItemOnCursor(new ItemStack(Material.AIR));
} else {
@@ -1,5 +1,6 @@
package me.barny1094875.shulkerstackingog.ShulkerBoxHelpers;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
@@ -25,7 +26,16 @@ public class NormalRightClick {
if (currentItem.getAmount() < 64) {
event.getCurrentItem().setAmount(currentItem.getAmount() + 1);
event.getCursor().setAmount(cursorItem.getAmount() - 1);
int newCursorAmount = cursorItem.getAmount() - 1;
if (newCursorAmount <= 0) {
event.getWhoClicked().setItemOnCursor(new ItemStack(Material.AIR));
} else {
event.getCursor().setAmount(newCursorAmount);
}
event.setCancelled(true);
}
@@ -0,0 +1,101 @@
package me.barny1094875.shulkerstackingog.ShulkerBoxHelpers;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
public final class ShulkerBoxUtils {
private ShulkerBoxUtils() {
}
public static boolean isEmptyShulkerBox(ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR) {
return false;
}
if (!itemStack.getType().toString().contains("SHULKER_BOX")) {
return false;
}
if (!(itemStack.getItemMeta() instanceof BlockStateMeta)) {
return false;
}
BlockStateMeta meta = (BlockStateMeta) itemStack.getItemMeta();
if (!(meta.getBlockState() instanceof ShulkerBox shulkerBox)) {
return false;
}
return shulkerBox.getInventory().isEmpty();
}
public static int mergeIntoExistingStacks(Inventory inventory, ItemStack prototype, int amountToAdd) {
for (int i = 0; i < inventory.getSize() && amountToAdd > 0; i++) {
ItemStack slot = inventory.getItem(i);
if (!isEmptyShulkerBox(slot)) {
continue;
}
if (!slot.getType().equals(prototype.getType())) {
continue;
}
int space = 64 - slot.getAmount();
if (space <= 0) {
continue;
}
int moved = Math.min(space, amountToAdd);
slot.setAmount(slot.getAmount() + moved);
amountToAdd -= moved;
}
return amountToAdd;
}
public static int fillEmptySlots(Inventory inventory, ItemStack prototype, int amountToAdd) {
for (int i = 0; i < inventory.getSize() && amountToAdd > 0; i++) {
ItemStack slot = inventory.getItem(i);
if (slot != null && slot.getType() != Material.AIR) {
continue;
}
int moved = Math.min(64, amountToAdd);
inventory.setItem(i, new ItemStack(prototype.getType(), moved));
amountToAdd -= moved;
}
return amountToAdd;
}
}
@@ -22,6 +22,7 @@ public final class ShulkerStacking_OG extends JavaPlugin {
getServer().getPluginManager().registerEvents(new ShulkerDragHandler(), this);
getServer().getPluginManager().registerEvents(new ShulkerDragDupePrevention(), this);
getServer().getPluginManager().registerEvents(new ShulkerBoxHopperHandler(), this);
getServer().getPluginManager().registerEvents(new ShulkerBoxMergeHandler(), this);
}