Dupe prevention update
This commit is contained in:
1 parent
92709bf88d
commit
b5e589ba41
14 files changed
+415
-508
No files matched your search
+1
-1
@@ -25,7 +25,7 @@ kotlin { jvmToolchain(17) }
|
||||
/* ----------------------------- Metadata ------------------------------ */
|
||||
group = "net.trueog.shulkerstacking-og" // Declare bundle identifier.
|
||||
|
||||
version = "1.1" // Declare plugin version (will be in .jar).
|
||||
version = "1.2" // Declare plugin version (will be in .jar).
|
||||
|
||||
val apiVersion = "1.19" // Declare minecraft server target version.
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package plugin.Listeners;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryMoveItemEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
@@ -10,7 +11,7 @@ import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
|
||||
|
||||
public class ShulkerBoxHopperHandler implements Listener {
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void shulkerBoxHopperHandler(InventoryMoveItemEvent event) {
|
||||
|
||||
ItemStack eventItem = event.getItem();
|
||||
@@ -22,9 +23,15 @@ public class ShulkerBoxHopperHandler implements Listener {
|
||||
|
||||
}
|
||||
|
||||
int toMove = eventItem.getAmount();
|
||||
if (toMove <= 0) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
int toMove = eventItem.getAmount();
|
||||
for (int i = 0; i < eventSource.getSize() && toMove > 0; i++) {
|
||||
|
||||
ItemStack sourceItem = eventSource.getItem(i);
|
||||
@@ -48,12 +55,8 @@ public class ShulkerBoxHopperHandler implements Listener {
|
||||
if (moved > 0) {
|
||||
|
||||
sourceItem.setAmount(sourceItem.getAmount() - moved);
|
||||
eventSource.setItem(i, sourceItem.getAmount() <= 0 ? null : sourceItem);
|
||||
toMove -= moved;
|
||||
if (sourceItem.getAmount() <= 0) {
|
||||
|
||||
eventSource.setItem(i, null);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package plugin.Listeners;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.ItemMergeEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -9,7 +10,7 @@ import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
|
||||
|
||||
public class ShulkerBoxMergeHandler implements Listener {
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onItemMerge(ItemMergeEvent event) {
|
||||
|
||||
ItemStack target = event.getTarget().getItemStack();
|
||||
@@ -38,6 +39,8 @@ public class ShulkerBoxMergeHandler implements Listener {
|
||||
|
||||
int moved = Math.min(space, source.getAmount());
|
||||
target.setAmount(target.getAmount() + moved);
|
||||
// Write back because Item#getItemStack may return a defensive copy.
|
||||
event.getTarget().setItemStack(target);
|
||||
int remaining = source.getAmount() - moved;
|
||||
|
||||
if (remaining <= 0) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package plugin.Listeners;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
@@ -12,7 +13,7 @@ import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
|
||||
|
||||
public class ShulkerBoxPickupHandler implements Listener {
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void shulkerBoxStacking(EntityPickupItemEvent event) {
|
||||
|
||||
ItemStack item = event.getItem().getItemStack();
|
||||
@@ -33,8 +34,9 @@ public class ShulkerBoxPickupHandler implements Listener {
|
||||
|
||||
Player player = (Player) event.getEntity();
|
||||
Inventory playerInventory = player.getInventory();
|
||||
int original = item.getAmount();
|
||||
|
||||
int remaining = item.getAmount();
|
||||
int remaining = original;
|
||||
remaining = ShulkerBoxUtils.mergeIntoExistingStacks(playerInventory, item, remaining);
|
||||
remaining = ShulkerBoxUtils.fillEmptySlots(playerInventory, item, remaining);
|
||||
|
||||
@@ -46,8 +48,15 @@ public class ShulkerBoxPickupHandler implements Listener {
|
||||
|
||||
}
|
||||
|
||||
ItemStack remainingItem = new ItemStack(item.getType(), remaining);
|
||||
event.getItem().setItemStack(remainingItem);
|
||||
// Preserve entity metadata when the inventory could not accept any items.
|
||||
if (remaining < original) {
|
||||
|
||||
ItemStack remainingItem = item.clone();
|
||||
remainingItem.setAmount(remaining);
|
||||
event.getItem().setItemStack(remainingItem);
|
||||
|
||||
}
|
||||
|
||||
player.updateInventory();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package plugin.Listeners;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
@@ -10,126 +15,142 @@ import plugin.ShulkerBoxHelpers.DoubleClick;
|
||||
import plugin.ShulkerBoxHelpers.NormalLeftClick;
|
||||
import plugin.ShulkerBoxHelpers.NormalRightClick;
|
||||
import plugin.ShulkerBoxHelpers.ShiftRightLeftClick;
|
||||
import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
|
||||
|
||||
public class ShulkerBoxStackingController implements Listener {
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void shulkerBoxStacking(InventoryClickEvent event) {
|
||||
|
||||
if (event.getCurrentItem() == null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (event.getCursor() == null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
ItemStack currentItem = event.getCurrentItem();
|
||||
ItemStack cursorItem = event.getCursor();
|
||||
ClickType click = event.getClick();
|
||||
|
||||
// If the player combines two shulker stacks...
|
||||
if (event.getClick().equals(ClickType.LEFT)) {
|
||||
boolean currentIsShulker = ShulkerBoxUtils.isShulkerBoxMaterial(currentItem);
|
||||
boolean cursorIsShulker = ShulkerBoxUtils.isShulkerBoxMaterial(cursorItem);
|
||||
|
||||
if (currentItem.getType().toString().contains("SHULKER_BOX")) {
|
||||
if (click.equals(ClickType.LEFT) && currentIsShulker && cursorIsShulker
|
||||
&& currentItem.getType().equals(cursorItem.getType()))
|
||||
{
|
||||
|
||||
if (cursorItem.getType().equals(currentItem.getType())) {
|
||||
if (ShulkerBoxUtils.isEmptyShulkerBox(currentItem) && ShulkerBoxUtils.isEmptyShulkerBox(cursorItem)) {
|
||||
|
||||
NormalLeftClick.NormalLeftClickShulkerBox(currentItem, cursorItem, event);
|
||||
return;
|
||||
NormalLeftClick.NormalLeftClickShulkerBox(currentItem, cursorItem, event);
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
// Filled shulkers cannot use vanilla NBT stacking.
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// if the player sets down just one shulker box from a stack
|
||||
if (event.getClick().equals(ClickType.RIGHT)) {
|
||||
if (click.equals(ClickType.RIGHT) && currentIsShulker && cursorIsShulker
|
||||
&& currentItem.getType().equals(cursorItem.getType()))
|
||||
{
|
||||
|
||||
if (currentItem.getType().toString().contains("SHULKER_BOX")) {
|
||||
if (ShulkerBoxUtils.isEmptyShulkerBox(currentItem) && ShulkerBoxUtils.isEmptyShulkerBox(cursorItem)) {
|
||||
|
||||
if (cursorItem.getType().equals(currentItem.getType())) {
|
||||
NormalRightClick.NormalRightClickShulkerBox(currentItem, cursorItem, event);
|
||||
|
||||
NormalRightClick.NormalRightClickShulkerBox(currentItem, cursorItem, event);
|
||||
} else {
|
||||
|
||||
}
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if the player puts down a shulker box stack
|
||||
if (event.getClick().equals(ClickType.LEFT)) {
|
||||
|
||||
if (cursorItem.getType().toString().contains("SHULKER_BOX")) {
|
||||
|
||||
// check if the shulker box stack only contains one shulker box
|
||||
if (cursorItem.getAmount() != 1) {
|
||||
|
||||
// remove the stack from their cursor
|
||||
// and replace it with whatever was in the slot
|
||||
event.getWhoClicked().setItemOnCursor(currentItem);
|
||||
// place down the whole stack
|
||||
event.setCurrentItem(cursorItem);
|
||||
// stop default behaviors
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// if the player double clicked in the inventory on a shulker box
|
||||
// gather all of the shulker boxes in the inventory to the player's cursor
|
||||
// including in their inventory
|
||||
// Place the whole empty cursor stack into air or a non-shulker slot.
|
||||
if (click.equals(ClickType.LEFT) && cursorIsShulker && cursorItem.getAmount() > 1) {
|
||||
|
||||
if (event.getClick().equals(ClickType.DOUBLE_CLICK)) {
|
||||
if (!ShulkerBoxUtils.isEmptyShulkerBox(cursorItem)) {
|
||||
|
||||
if (cursorItem.getType().toString().contains("SHULKER_BOX")) {
|
||||
|
||||
DoubleClick.DoubleClickShulkerBox(cursorItem, event);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (currentItem == null || currentItem.getType() == Material.AIR) {
|
||||
|
||||
event.setCurrentItem(cursorItem);
|
||||
event.getWhoClicked().setItemOnCursor(new ItemStack(Material.AIR));
|
||||
event.setCancelled(true);
|
||||
|
||||
} else if (!currentIsShulker) {
|
||||
|
||||
event.getWhoClicked().setItemOnCursor(currentItem);
|
||||
event.setCurrentItem(cursorItem);
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// if the player shift clicks on a shukler box stack
|
||||
// we need to handle the stacking logic
|
||||
if (event.getClick().equals(ClickType.SHIFT_LEFT) || event.getClick().equals(ClickType.SHIFT_RIGHT)) {
|
||||
if (click.equals(ClickType.DOUBLE_CLICK) && cursorIsShulker) {
|
||||
|
||||
if (currentItem.getType().toString().contains("SHULKER_BOX")) {
|
||||
if (ShulkerBoxUtils.isEmptyShulkerBox(cursorItem)) {
|
||||
|
||||
DoubleClick.DoubleClickShulkerBox(cursorItem, event);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if ((click.equals(ClickType.SHIFT_LEFT) || click.equals(ClickType.SHIFT_RIGHT)) && currentIsShulker) {
|
||||
|
||||
if (ShulkerBoxUtils.isEmptyShulkerBox(currentItem)) {
|
||||
|
||||
ShiftRightLeftClick.ShiftRightLeftClickShulkerBox(event);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// if the player users CTRL+<drop> on the shulkers
|
||||
// drop the whole stack, instead of just one
|
||||
if (event.getClick().equals(ClickType.CONTROL_DROP)) {
|
||||
// Drop the whole empty stack; vanilla correctly drops filled single boxes.
|
||||
if (click.equals(ClickType.CONTROL_DROP) && currentIsShulker && currentItem.getAmount() > 1) {
|
||||
|
||||
if (currentItem.getType().toString().contains("SHULKER_BOX")) {
|
||||
if (!ShulkerBoxUtils.isEmptyShulkerBox(currentItem)) {
|
||||
|
||||
event.getWhoClicked().getWorld().dropItem(event.getWhoClicked().getLocation(), event.getCurrentItem(),
|
||||
(Item) ->
|
||||
{
|
||||
|
||||
Item.setVelocity(
|
||||
event.getWhoClicked().getLocation().getDirection().multiply(0.35).setY(0.25));
|
||||
|
||||
});
|
||||
event.getCurrentItem().setAmount(0);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
HumanEntity who = event.getWhoClicked();
|
||||
Location dropLoc = who.getLocation();
|
||||
ItemStack dropStack = currentItem.clone();
|
||||
Item dropped = who.getWorld().dropItem(dropLoc, dropStack, (Item entity) -> {
|
||||
|
||||
entity.setVelocity(dropLoc.getDirection().multiply(0.35).setY(0.25));
|
||||
|
||||
});
|
||||
// Clear the slot only if ItemSpawnEvent allowed the drop entity.
|
||||
if (dropped != null && dropped.isValid() && !dropped.isDead()) {
|
||||
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Block creative middle-clone because empty shulkers would be synthesized.
|
||||
if (click.equals(ClickType.MIDDLE) && currentIsShulker) {
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package plugin.Listeners;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import plugin.ShulkerStackingOG;
|
||||
|
||||
public class ShulkerCleanupHandler implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
|
||||
// Remove the close flag when the player quits to prevent stale entries.
|
||||
ShulkerStackingOG.isInventoryClosed.remove(event.getPlayer().getUniqueId());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,10 +13,12 @@ public class ShulkerDragDupePrevention implements Listener {
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void shulkerDragDupePrevent(InventoryCloseEvent event) {
|
||||
|
||||
ShulkerStackingOG.isInventoryClosed.put(event.getPlayer().getUniqueId(), true);
|
||||
java.util.UUID uuid = event.getPlayer().getUniqueId();
|
||||
ShulkerStackingOG.isInventoryClosed.put(uuid, true);
|
||||
// Reset flags only if present so delayed tasks cannot recreate stale state.
|
||||
Bukkit.getScheduler().runTaskLater(ShulkerStackingOG.getPlugin(),
|
||||
() -> ShulkerStackingOG.isInventoryClosed.put(event.getPlayer().getUniqueId(), false), 2);
|
||||
() -> ShulkerStackingOG.isInventoryClosed.computeIfPresent(uuid, (k, v) -> false), 2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package plugin.Listeners;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
@@ -11,131 +12,204 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.DragType;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import plugin.ShulkerBoxHelpers.ShulkerBoxUtils;
|
||||
import plugin.ShulkerStackingOG;
|
||||
|
||||
public class ShulkerDragHandler implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void shulkerBoxDrag(InventoryDragEvent event) {
|
||||
|
||||
if (!event.getOldCursor().getType().toString().contains("SHULKER_BOX")) {
|
||||
ItemStack cursor = event.getOldCursor();
|
||||
if (!ShulkerBoxUtils.isShulkerBoxMaterial(cursor)) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Cancel leaked filled stacks before vanilla can split duplicate NBT.
|
||||
if (!ShulkerBoxUtils.isEmptyShulkerBox(cursor)) {
|
||||
|
||||
if (cursor.getAmount() > 1) {
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Disable default behavior.
|
||||
event.setCancelled(true);
|
||||
|
||||
final int total = cursor.getAmount();
|
||||
if (total < 1) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
final Material shulkerType = cursor.getType();
|
||||
final DragType dragType = event.getType();
|
||||
final Set<Integer> rawSlots = event.getRawSlots();
|
||||
final int slotCount = rawSlots.size();
|
||||
if (slotCount == 0) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
final int perSlot;
|
||||
if (dragType.equals(DragType.SINGLE)) {
|
||||
|
||||
perSlot = 1;
|
||||
|
||||
} else if (dragType.equals(DragType.EVEN)) {
|
||||
|
||||
perSlot = total / slotCount;
|
||||
|
||||
} else {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (perSlot <= 0) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
final InventoryView view = event.getView();
|
||||
|
||||
Bukkit.getScheduler().runTask(ShulkerStackingOG.getPlugin(), () -> {
|
||||
|
||||
// Check if the inventory was closed in the last tick.
|
||||
// This prevents a duplication glitch from occurring.
|
||||
if (ShulkerStackingOG.isInventoryClosed.get(event.getWhoClicked().getUniqueId())) {
|
||||
// Skip if inventory just closed: vanilla already ejected cursor contents.
|
||||
Boolean closed = ShulkerStackingOG.isInventoryClosed.get(event.getWhoClicked().getUniqueId());
|
||||
if (closed != null && closed) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
ItemStack shulkerBoxes = event.getOldCursor();
|
||||
int numberOfSlotsDragged = event.getInventorySlots().size();
|
||||
ArrayList<Integer> slotsDragged = new ArrayList<>(event.getInventorySlots().stream().toList());
|
||||
Inventory dragInventory = event.getView().getBottomInventory();
|
||||
// Right click drag.
|
||||
if (event.getType().equals(DragType.SINGLE)) {
|
||||
// Abort if vanilla dropped the cursor while the player went offline.
|
||||
if (!(event.getWhoClicked() instanceof Player player) || !player.isOnline()) {
|
||||
|
||||
// If the player drags a stack of shulker boxes.
|
||||
if (shulkerBoxes.getAmount() <= 1) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Set each slot to the appropriate amount of shulkers.
|
||||
for (int i = 0; i < numberOfSlotsDragged; i++) {
|
||||
|
||||
if (dragInventory.getItem(slotsDragged.get(i)) == null
|
||||
|| dragInventory.getItem(slotsDragged.get(i)).getType() == Material.AIR)
|
||||
{
|
||||
|
||||
dragInventory.setItem(slotsDragged.get(i), new ItemStack(shulkerBoxes.getType(), 1));
|
||||
|
||||
} else if (dragInventory.getItem(slotsDragged.get(i)) != null
|
||||
&& dragInventory.getItem(slotsDragged.get(i)).getType().equals(shulkerBoxes.getType()))
|
||||
{
|
||||
|
||||
dragInventory.getItem(slotsDragged.get(i))
|
||||
.setAmount(dragInventory.getItem(slotsDragged.get(i)).getAmount() + 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// remove the shulker boxes from the player's cursor
|
||||
event.getWhoClicked().setItemOnCursor(
|
||||
new ItemStack(shulkerBoxes.getType(), shulkerBoxes.getAmount() - numberOfSlotsDragged));
|
||||
return;
|
||||
|
||||
}
|
||||
// left click drag
|
||||
else if (event.getType().equals(DragType.EVEN)) {
|
||||
|
||||
// if the player drags a stack of shulker boxes
|
||||
if (shulkerBoxes.getAmount() <= 1) {
|
||||
// Abort if a Q-drop, hotbar swap, or outside-click changed the cursor.
|
||||
ItemStack live = player.getItemOnCursor();
|
||||
if (!ShulkerBoxUtils.isEmptyShulkerBox(live) || !live.getType().equals(shulkerType)
|
||||
|| live.getAmount() < total)
|
||||
{
|
||||
|
||||
return;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// set each slot to the appropriate amount of shulkers
|
||||
for (int i = 0; i < numberOfSlotsDragged; i++) {
|
||||
// Increment before slot writes so exceptions bias toward loss, not duplication.
|
||||
int[] placedRef = new int[] { 0 };
|
||||
int[] pendingRef = new int[] { 0 };
|
||||
try {
|
||||
|
||||
if (dragInventory.getItem(slotsDragged.get(i)) == null
|
||||
|| dragInventory.getItem(slotsDragged.get(i)).getType() == Material.AIR)
|
||||
{
|
||||
for (Integer rawSlot : rawSlots) {
|
||||
|
||||
ItemStack newShulkerBoxes = new ItemStack(shulkerBoxes.getType(),
|
||||
shulkerBoxes.getAmount() / numberOfSlotsDragged);
|
||||
dragInventory.setItem(slotsDragged.get(i), newShulkerBoxes);
|
||||
if (newShulkerBoxes.getAmount() > 64) {
|
||||
if (placedRef[0] >= total) {
|
||||
|
||||
shulkerBoxes.setAmount(shulkerBoxes.getAmount() - (64 - shulkerBoxes.getAmount()));
|
||||
newShulkerBoxes.setAmount(64);
|
||||
slotsDragged.remove(i);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
dragInventory.setItem(slotsDragged.get(i), newShulkerBoxes);
|
||||
|
||||
} else if (dragInventory.getItem(slotsDragged.get(i)) != null
|
||||
&& dragInventory.getItem(slotsDragged.get(i)).getType().equals(shulkerBoxes.getType()))
|
||||
{
|
||||
|
||||
ItemStack newShulkerBoxes = new ItemStack(shulkerBoxes.getType(),
|
||||
shulkerBoxes.getAmount() / numberOfSlotsDragged);
|
||||
dragInventory.getItem(slotsDragged.get(i))
|
||||
.setAmount(dragInventory.getItem(slotsDragged.get(i)).getAmount()
|
||||
+ shulkerBoxes.getAmount() / numberOfSlotsDragged);
|
||||
if (newShulkerBoxes.getAmount() > 64) {
|
||||
|
||||
shulkerBoxes.setAmount(shulkerBoxes.getAmount() - (64 - shulkerBoxes.getAmount()));
|
||||
newShulkerBoxes.setAmount(64);
|
||||
slotsDragged.remove(i);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
dragInventory.setItem(slotsDragged.get(i), newShulkerBoxes);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
Inventory targetInv = view.getInventory(rawSlot);
|
||||
if (targetInv == null) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
int slotIdx = view.convertSlot(rawSlot);
|
||||
if (slotIdx < 0 || slotIdx >= targetInv.getSize()) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
ItemStack existing = targetInv.getItem(slotIdx);
|
||||
|
||||
int desired = Math.min(perSlot, total - placedRef[0]);
|
||||
|
||||
if (existing == null || existing.getType() == Material.AIR) {
|
||||
|
||||
int toPlace = Math.min(desired, 64);
|
||||
pendingRef[0] = toPlace;
|
||||
placedRef[0] += toPlace;
|
||||
targetInv.setItem(slotIdx, new ItemStack(shulkerType, toPlace));
|
||||
pendingRef[0] = 0;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (!ShulkerBoxUtils.isEmptyShulkerBox(existing)) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (!existing.getType().equals(shulkerType)) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
int space = 64 - existing.getAmount();
|
||||
if (space <= 0) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
int toAdd = Math.min(desired, space);
|
||||
pendingRef[0] = toAdd;
|
||||
placedRef[0] += toAdd;
|
||||
existing.setAmount(existing.getAmount() + toAdd);
|
||||
targetInv.setItem(slotIdx, existing);
|
||||
pendingRef[0] = 0;
|
||||
|
||||
}
|
||||
|
||||
event.getWhoClicked().setItemOnCursor(
|
||||
new ItemStack(shulkerBoxes.getType(), shulkerBoxes.getAmount() % numberOfSlotsDragged));
|
||||
((Player) event.getWhoClicked()).updateInventory();
|
||||
} catch (RuntimeException exception) {
|
||||
|
||||
if (pendingRef[0] > 0) {
|
||||
|
||||
ShulkerStackingOG.getPlugin().getLogger().log(Level.SEVERE,
|
||||
"Suspected loss of up to " + pendingRef[0] + " " + shulkerType
|
||||
+ " shulker boxes during an inventory drag for " + player.getName() + " ("
|
||||
+ player.getUniqueId() + ").",
|
||||
exception);
|
||||
|
||||
}
|
||||
|
||||
throw exception;
|
||||
|
||||
} finally {
|
||||
|
||||
int leftover = total - placedRef[0];
|
||||
if (leftover <= 0) {
|
||||
|
||||
player.setItemOnCursor(new ItemStack(Material.AIR));
|
||||
|
||||
} else {
|
||||
|
||||
player.setItemOnCursor(new ItemStack(shulkerType, leftover));
|
||||
|
||||
}
|
||||
|
||||
player.updateInventory();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -14,49 +14,33 @@ public class DoubleClick {
|
||||
|
||||
public static void DoubleClickShulkerBox(ItemStack cursorItem, InventoryClickEvent event) {
|
||||
|
||||
// check that the held shulker box is empty
|
||||
// Only empty shulkers can be collected.
|
||||
Inventory heldShulkerInventory = ((ShulkerBox) ((BlockStateMeta) cursorItem.getItemMeta()).getBlockState())
|
||||
.getInventory();
|
||||
if (heldShulkerInventory.isEmpty()) {
|
||||
|
||||
// loop through the inventory, and the player's inventory
|
||||
// and count up the shulker boxes
|
||||
// ignore boxes in result slots
|
||||
// delete the shulker boxes, up to 64, and set the cursor stack
|
||||
// to the number of boxes, up to 64
|
||||
// Collect up to 64 matching empty shulkers from both inventories.
|
||||
InventoryView eventView = event.getView();
|
||||
Inventory playerInventory = eventView.getBottomInventory();
|
||||
Inventory containerInventory = eventView.getTopInventory();
|
||||
Material shulkerType = cursorItem.getType();
|
||||
int containerSize = containerInventory.getSize();
|
||||
|
||||
// store a temporary inventory so that we can handle
|
||||
// full shulker boxes
|
||||
// Use temporary inventories to skip filled shulkers without removing them.
|
||||
Inventory tempPlayerInventory = Bukkit.createInventory(null, 36);
|
||||
tempPlayerInventory.setContents(playerInventory.getContents());
|
||||
// make the inventory size the max of 54 so that it will hold any size inventory
|
||||
// Use the maximum container size so every view fits.
|
||||
Inventory tempContainerInventory = Bukkit.createInventory(null, 54);
|
||||
tempContainerInventory.setContents(containerInventory.getContents());
|
||||
|
||||
// use these two inventories to loop through the inventories
|
||||
// we can delete full shulkers from these temporary inventories
|
||||
// without deleting them from the main inventory
|
||||
// and then just copy over the empty shulker deletes to the main
|
||||
// inventories
|
||||
|
||||
// loop through the container inventory until there are no
|
||||
// more shulker boxes, counting them up, and removing them
|
||||
// up to 64 boxes
|
||||
// Collect empty shulkers from the container first.
|
||||
int shulkerBoxCount = cursorItem.getAmount();
|
||||
while (tempContainerInventory.first(shulkerType) != -1) {
|
||||
|
||||
int firstShulker = tempContainerInventory.first(shulkerType);
|
||||
// grab the inventory of the shulker box in that slot
|
||||
Inventory shulkerInventory = ((ShulkerBox) ((BlockStateMeta) tempContainerInventory
|
||||
.getItem(firstShulker).getItemMeta()).getBlockState()).getInventory();
|
||||
// if that inventory is not empty, delete it from the temporary inventory, and
|
||||
// continue on
|
||||
// otherwise, do the rest of the logic
|
||||
// Skip filled shulkers in the temporary inventory.
|
||||
if (!shulkerInventory.isEmpty()) {
|
||||
|
||||
tempContainerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
|
||||
@@ -64,8 +48,7 @@ public class DoubleClick {
|
||||
|
||||
}
|
||||
|
||||
// if the shulker box is in a RESULT slot, then break from
|
||||
// the loop, since that is always the last slot
|
||||
// Result slots terminate the top-inventory scan.
|
||||
InventoryType.SlotType slotType = eventView.getSlotType(firstShulker);
|
||||
if (slotType.equals(InventoryType.SlotType.RESULT)) {
|
||||
|
||||
@@ -73,24 +56,18 @@ public class DoubleClick {
|
||||
|
||||
}
|
||||
|
||||
// if the shulker box count would have gone above 64
|
||||
ItemStack shulkerStackItem = containerInventory.getItem(firstShulker);
|
||||
int shulkerStackAmount = shulkerStackItem.getAmount();
|
||||
if (shulkerBoxCount + shulkerStackAmount > 64) {
|
||||
|
||||
// get how many shulker boxes we need to get to 64
|
||||
int shulkersRequired = 64 - shulkerBoxCount;
|
||||
// remove that many boxes from the stack
|
||||
shulkerStackItem.setAmount(shulkerStackAmount - shulkersRequired);
|
||||
shulkerBoxCount += shulkersRequired;
|
||||
// break from the loop, since we have a stack of shulkers collected
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
// add the shulkerStackAmount to shulkerBoxCount
|
||||
shulkerBoxCount += shulkerStackAmount;
|
||||
// remove the shulkers from that slot
|
||||
containerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
|
||||
tempContainerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
|
||||
|
||||
@@ -98,28 +75,22 @@ public class DoubleClick {
|
||||
|
||||
}
|
||||
|
||||
// loop through the player's inventory
|
||||
// Collect empty shulkers from the player's inventory next.
|
||||
while (tempPlayerInventory.first(shulkerType) != -1) {
|
||||
|
||||
int firstShulker = tempPlayerInventory.first(shulkerType);
|
||||
|
||||
// grab the inventory of the shulker box in that slot
|
||||
Inventory shulkerInventory = ((ShulkerBox) ((BlockStateMeta) tempPlayerInventory.getItem(firstShulker)
|
||||
.getItemMeta()).getBlockState()).getInventory();
|
||||
// if that inventory is not empty, delete it from the temporary inventory, and
|
||||
// continue on
|
||||
// otherwise, do the rest of the logic
|
||||
// Skip filled shulkers in the temporary inventory.
|
||||
if (!shulkerInventory.isEmpty()) {
|
||||
|
||||
// remove this non-empty shulker from the temporary inventory
|
||||
tempPlayerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// if the shulker box is in a RESULT slot, then break from
|
||||
// the loop, since that is always the last slot
|
||||
// add the container's size to the here to offset it to the player's inventory
|
||||
// Offset by the container size before checking the raw slot type.
|
||||
InventoryType.SlotType slotType = eventView.getSlotType(firstShulker + containerSize);
|
||||
if (slotType.equals(InventoryType.SlotType.RESULT)) {
|
||||
|
||||
@@ -127,24 +98,18 @@ public class DoubleClick {
|
||||
|
||||
}
|
||||
|
||||
// if the shulker box count would have gone above 64
|
||||
ItemStack shulkerStackItem = playerInventory.getItem(firstShulker);
|
||||
int shulkerStackAmount = shulkerStackItem.getAmount();
|
||||
if (shulkerBoxCount + shulkerStackAmount > 64) {
|
||||
|
||||
// get how many shulker boxes we need to get to 64
|
||||
int shulkersRequired = 64 - shulkerBoxCount;
|
||||
// remove that many boxes from the stack
|
||||
shulkerStackItem.setAmount(shulkerStackAmount - shulkersRequired);
|
||||
shulkerBoxCount += shulkersRequired;
|
||||
// break from the loop, since we have a stack of shulkers collected
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
// add the shulkerStackAmount to shulkerBoxCount
|
||||
shulkerBoxCount += shulkerStackAmount;
|
||||
// remove the shulkers from that slot
|
||||
playerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
|
||||
tempPlayerInventory.setItem(firstShulker, new ItemStack(Material.AIR));
|
||||
|
||||
@@ -152,14 +117,12 @@ public class DoubleClick {
|
||||
|
||||
}
|
||||
|
||||
// now that we have the number of shulkers to grab, put them into the cursor
|
||||
// if the shulkerBoxCount was 1, then don't do anything
|
||||
// Update the cursor only after collecting more than one shulker.
|
||||
if (shulkerBoxCount != 1) {
|
||||
|
||||
ItemStack newShulkers = new ItemStack(shulkerType);
|
||||
newShulkers.setAmount(shulkerBoxCount);
|
||||
event.getWhoClicked().setItemOnCursor(newShulkers);
|
||||
// cancel default behavior
|
||||
event.setCancelled(true);
|
||||
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ public class NormalLeftClick {
|
||||
InventoryClickEvent event)
|
||||
{
|
||||
|
||||
// check that both shulker boxes are empty
|
||||
// get the inventories of the shulker boxes
|
||||
// Read both inventories before stacking empty shulkers.
|
||||
BlockStateMeta shulker1Meta = (BlockStateMeta) currentItem.getItemMeta();
|
||||
BlockStateMeta shulker2Meta = (BlockStateMeta) cursorItem.getItemMeta();
|
||||
ShulkerBox shulker1 = (ShulkerBox) shulker1Meta.getBlockState();
|
||||
@@ -32,7 +31,7 @@ public class NormalLeftClick {
|
||||
|
||||
} else {
|
||||
|
||||
// add the shulkers until we are at 64
|
||||
// Add shulkers until the target reaches 64.
|
||||
event.getWhoClicked().getItemOnCursor()
|
||||
.setAmount((currentItem.getAmount() + cursorItem.getAmount()) - 64);
|
||||
event.getCurrentItem().setAmount(64);
|
||||
|
||||
@@ -12,8 +12,7 @@ public class NormalRightClick {
|
||||
InventoryClickEvent event)
|
||||
{
|
||||
|
||||
// check that both shulker boxes are empty
|
||||
// get the inventories of the shulker boxes
|
||||
// Read both inventories before stacking empty shulkers.
|
||||
BlockStateMeta shulker1Meta = (BlockStateMeta) currentItem.getItemMeta();
|
||||
BlockStateMeta shulker2Meta = (BlockStateMeta) cursorItem.getItemMeta();
|
||||
ShulkerBox shulker1 = (ShulkerBox) shulker1Meta.getBlockState();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package plugin.ShulkerBoxHelpers;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
@@ -12,299 +11,106 @@ public class ShiftRightLeftClick {
|
||||
|
||||
public static void ShiftRightLeftClickShulkerBox(InventoryClickEvent event) {
|
||||
|
||||
// check what kind of inventory was shift-clicked in
|
||||
// regardless, loop through the inventory(ies) and add the
|
||||
// shulker box stack to the
|
||||
InventoryView eventInventory = event.getView();
|
||||
InventoryType inventoryType = eventInventory.getType();
|
||||
Inventory containerInventory = eventInventory.getTopInventory();
|
||||
Inventory playerInventory = eventInventory.getBottomInventory();
|
||||
// store a temporary inventory so that we can handle
|
||||
// full shulker boxes
|
||||
Inventory tempPlayerInventory = Bukkit.createInventory(null, 36);
|
||||
tempPlayerInventory.setContents(playerInventory.getContents());
|
||||
// make the inventory size the max of 54 so that it will hold any size inventory
|
||||
Inventory tempContainerInventory = Bukkit.createInventory(null, 54);
|
||||
tempContainerInventory.setContents(containerInventory.getContents());
|
||||
Material shulkerBoxType = event.getCurrentItem().getType();
|
||||
int shulkerStackAmount = event.getCurrentItem().getAmount();
|
||||
ItemStack source = event.getCurrentItem();
|
||||
if (!ShulkerBoxUtils.isEmptyShulkerBox(source)) {
|
||||
|
||||
// if it was the player's inventory
|
||||
if (inventoryType.equals(InventoryType.CRAFTING)) {
|
||||
|
||||
// check if the slot was a hotbar slot or not
|
||||
if (event.getSlotType().equals(InventoryType.SlotType.QUICKBAR)) {
|
||||
|
||||
// remove the hotbar of the tempInventory
|
||||
for (int i = 0; i < 9; i++) {
|
||||
|
||||
tempPlayerInventory.setItem(i, new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
// check the top part of the inventory for any shulker stacks that are not 64
|
||||
// yet
|
||||
while (tempPlayerInventory.first(shulkerBoxType) != -1) {
|
||||
|
||||
int firstShulkerSlot = tempPlayerInventory.first(shulkerBoxType);
|
||||
ItemStack shulkerStack = tempPlayerInventory.getItem(firstShulkerSlot);
|
||||
// if the shulker stack has 64 shulker boxes in it
|
||||
// remove it from the temporary inventory and continue on
|
||||
if (shulkerStack.getAmount() >= 64) {
|
||||
|
||||
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// cancel default behavior since shulker boxes are being moved
|
||||
event.setCancelled(true);
|
||||
|
||||
// stack up to 64 shulkers into the stack, and then continue on
|
||||
if (shulkerStack.getAmount() + shulkerStackAmount <= 64) {
|
||||
|
||||
playerInventory.getItem(firstShulkerSlot)
|
||||
.setAmount(shulkerStack.getAmount() + shulkerStackAmount);
|
||||
shulkerStackAmount = 0;
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
// remove shulker boxes until the shulker stack has 64 boxes
|
||||
shulkerStackAmount -= 64 - shulkerStack.getAmount();
|
||||
playerInventory.getItem(firstShulkerSlot).setAmount(64);
|
||||
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// change the shulker stack amount to what is left
|
||||
// or remove it if nothing is left
|
||||
if (shulkerStackAmount == 0) {
|
||||
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
} else {
|
||||
|
||||
event.getCurrentItem().setAmount(shulkerStackAmount);
|
||||
// look for an air gap to put the rest of the shulker boxes
|
||||
for (int i = 9; i < playerInventory.getSize(); i++) {
|
||||
|
||||
if (playerInventory.getItem(i) == null) {
|
||||
|
||||
playerInventory.setItem(i, event.getCurrentItem());
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// the slot was an inventory slot, so check the hotbar for boxes
|
||||
else {
|
||||
|
||||
// remove everything from the upper inventory to prevent it from causing
|
||||
// problems
|
||||
for (int i = 35; i > 8; i--) {
|
||||
|
||||
tempPlayerInventory.setItem(i, new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
while (tempPlayerInventory.first(shulkerBoxType) != -1) {
|
||||
|
||||
int firstShulkerSlot = tempPlayerInventory.first(shulkerBoxType);
|
||||
ItemStack shulkerStack = tempPlayerInventory.getItem(firstShulkerSlot);
|
||||
// if the shulker stack has 64 shulker boxes in it
|
||||
// remove it from the temporary inventory and continue on
|
||||
if (shulkerStack.getAmount() >= 64) {
|
||||
|
||||
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// cancel default behavior since shulker boxes are being moved
|
||||
event.setCancelled(true);
|
||||
|
||||
// stack up to 64 shulkers into the stack, and then continue on
|
||||
if (shulkerStack.getAmount() + shulkerStackAmount <= 64) {
|
||||
|
||||
playerInventory.getItem(firstShulkerSlot)
|
||||
.setAmount(shulkerStack.getAmount() + shulkerStackAmount);
|
||||
shulkerStackAmount = 0;
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
// remove shulker boxes until the shulker stack has 64 boxes
|
||||
shulkerStackAmount -= 64 - shulkerStack.getAmount();
|
||||
playerInventory.getItem(firstShulkerSlot).setAmount(64);
|
||||
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// change the shulker stack amount to what is left
|
||||
// or remove it if nothing is left
|
||||
if (shulkerStackAmount == 0) {
|
||||
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
} else {
|
||||
|
||||
event.getCurrentItem().setAmount(shulkerStackAmount);
|
||||
// look for an air gap to put the rest of the shulker boxes
|
||||
for (int i = 0; i < 9; i++) {
|
||||
|
||||
if (playerInventory.getItem(i) == null) {
|
||||
|
||||
playerInventory.setItem(i, event.getCurrentItem());
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
// if it was anything else
|
||||
else {
|
||||
|
||||
// check if the click was in the bottom
|
||||
if (event.getRawSlot() > containerInventory.getSize()) {
|
||||
InventoryView view = event.getView();
|
||||
Inventory top = view.getTopInventory();
|
||||
Inventory bottom = view.getBottomInventory();
|
||||
InventoryType viewType = view.getType();
|
||||
Material shulkerType = source.getType();
|
||||
int rawSlot = event.getRawSlot();
|
||||
int topSize = top.getSize();
|
||||
boolean clickedTop = rawSlot < topSize;
|
||||
|
||||
while (tempContainerInventory.first(shulkerBoxType) != -1) {
|
||||
// Cancel default handling before redistributing the stack.
|
||||
event.setCancelled(true);
|
||||
|
||||
int firstShulkerSlot = tempContainerInventory.first(shulkerBoxType);
|
||||
ItemStack shulkerStack = tempContainerInventory.getItem(firstShulkerSlot);
|
||||
// if the shulker stack has 64 shulker boxes in it
|
||||
// remove it from the temporary inventory and continue on
|
||||
if (shulkerStack.getAmount() >= 64) {
|
||||
int remaining = source.getAmount();
|
||||
|
||||
tempContainerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
|
||||
continue;
|
||||
if (viewType.equals(InventoryType.CRAFTING)) {
|
||||
|
||||
}
|
||||
// Without a container open, shift within storage slots 0-35 only.
|
||||
boolean fromHotbar = event.getSlotType().equals(InventoryType.SlotType.QUICKBAR);
|
||||
int destStart = fromHotbar ? 9 : 0;
|
||||
int destEnd = fromHotbar ? Math.min(bottom.getSize(), 36) : 9;
|
||||
remaining = redistribute(bottom, destStart, destEnd, shulkerType, remaining);
|
||||
|
||||
// cancel default behavior since shulker boxes are being moved
|
||||
event.setCancelled(true);
|
||||
} else {
|
||||
|
||||
// stack up to 64 shulkers into the stack, and then continue on
|
||||
if (shulkerStack.getAmount() + shulkerStackAmount <= 64) {
|
||||
Inventory destination = clickedTop ? bottom : top;
|
||||
int destStart = 0;
|
||||
// Limit player destinations to storage slots 0-35, including non-vanilla views.
|
||||
int destEnd = (destination == bottom) ? Math.min(destination.getSize(), 36) : destination.getSize();
|
||||
remaining = redistribute(destination, destStart, destEnd, shulkerType, remaining);
|
||||
|
||||
containerInventory.getItem(firstShulkerSlot)
|
||||
.setAmount(shulkerStack.getAmount() + shulkerStackAmount);
|
||||
shulkerStackAmount = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (remaining <= 0) {
|
||||
|
||||
// remove shulker boxes until the shulker stack has 64 boxes
|
||||
shulkerStackAmount -= 64 - shulkerStack.getAmount();
|
||||
containerInventory.getItem(firstShulkerSlot).setAmount(64);
|
||||
tempContainerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
// change the shulker stack amount to what is left
|
||||
// or remove it if nothing is left
|
||||
if (shulkerStackAmount == 0) {
|
||||
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
} else {
|
||||
|
||||
event.getCurrentItem().setAmount(shulkerStackAmount);
|
||||
// look for an air gap to put the rest of the shulker boxes
|
||||
for (int i = 0; i < containerInventory.getSize(); i++) {
|
||||
|
||||
if (containerInventory.getItem(i) == null) {
|
||||
|
||||
containerInventory.setItem(i, event.getCurrentItem());
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// the click was in the top inventory
|
||||
else {
|
||||
|
||||
while (tempPlayerInventory.first(shulkerBoxType) != -1) {
|
||||
|
||||
int firstShulkerSlot = tempPlayerInventory.first(shulkerBoxType);
|
||||
ItemStack shulkerStack = tempPlayerInventory.getItem(firstShulkerSlot);
|
||||
// if the shulker stack has 64 shulker boxes in it
|
||||
// remove it from the temporary inventory and continue on
|
||||
if (shulkerStack.getAmount() >= 64) {
|
||||
|
||||
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// cancel default behavior since shulker boxes are being moved
|
||||
event.setCancelled(true);
|
||||
|
||||
// stack up to 64 shulkers into the stack, and then continue on
|
||||
if (shulkerStack.getAmount() + shulkerStackAmount <= 64) {
|
||||
|
||||
playerInventory.getItem(firstShulkerSlot)
|
||||
.setAmount(shulkerStack.getAmount() + shulkerStackAmount);
|
||||
shulkerStackAmount = 0;
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
// remove shulker boxes until the shulker stack has 64 boxes
|
||||
shulkerStackAmount -= 64 - shulkerStack.getAmount();
|
||||
playerInventory.getItem(firstShulkerSlot).setAmount(64);
|
||||
tempPlayerInventory.setItem(firstShulkerSlot, new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// change the shulker stack amount to what is left
|
||||
// or remove it if nothing is left
|
||||
if (shulkerStackAmount == 0) {
|
||||
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
} else {
|
||||
|
||||
event.getCurrentItem().setAmount(shulkerStackAmount);
|
||||
// look for an air gap to put the rest of the shulker boxes
|
||||
for (int i = 0; i < playerInventory.getSize(); i++) {
|
||||
|
||||
if (playerInventory.getItem(i) == null) {
|
||||
|
||||
playerInventory.setItem(i, event.getCurrentItem());
|
||||
event.setCurrentItem(new ItemStack(Material.AIR));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
event.setCurrentItem(new ItemStack(shulkerType, remaining));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int redistribute(Inventory inv, int start, int end, Material shulkerType, int amount) {
|
||||
|
||||
// Phase 1: top off existing empty stacks of the same material.
|
||||
for (int i = start; i < end && amount > 0; i++) {
|
||||
|
||||
ItemStack slot = inv.getItem(i);
|
||||
if (!ShulkerBoxUtils.isEmptyShulkerBox(slot)) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if (!slot.getType().equals(shulkerType)) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
int space = 64 - slot.getAmount();
|
||||
if (space <= 0) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
int moved = Math.min(space, amount);
|
||||
slot.setAmount(slot.getAmount() + moved);
|
||||
amount -= moved;
|
||||
|
||||
}
|
||||
|
||||
// Phase 2: drop leftovers into AIR slots, one stack at a time.
|
||||
for (int i = start; i < end && amount > 0; i++) {
|
||||
|
||||
ItemStack slot = inv.getItem(i);
|
||||
if (slot != null && slot.getType() != Material.AIR) {
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
int placed = Math.min(64, amount);
|
||||
inv.setItem(i, new ItemStack(shulkerType, placed));
|
||||
amount -= placed;
|
||||
|
||||
}
|
||||
|
||||
return amount;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,7 +12,7 @@ public final class ShulkerBoxUtils {
|
||||
|
||||
}
|
||||
|
||||
public static boolean isEmptyShulkerBox(ItemStack itemStack) {
|
||||
public static boolean isShulkerBoxMaterial(ItemStack itemStack) {
|
||||
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR) {
|
||||
|
||||
@@ -20,7 +20,13 @@ public final class ShulkerBoxUtils {
|
||||
|
||||
}
|
||||
|
||||
if (!itemStack.getType().toString().contains("SHULKER_BOX")) {
|
||||
return itemStack.getType().toString().contains("SHULKER_BOX");
|
||||
|
||||
}
|
||||
|
||||
public static boolean isEmptyShulkerBox(ItemStack itemStack) {
|
||||
|
||||
if (!isShulkerBoxMaterial(itemStack)) {
|
||||
|
||||
return false;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import plugin.Listeners.ShulkerBoxHopperHandler;
|
||||
import plugin.Listeners.ShulkerBoxMergeHandler;
|
||||
import plugin.Listeners.ShulkerBoxPickupHandler;
|
||||
import plugin.Listeners.ShulkerBoxStackingController;
|
||||
import plugin.Listeners.ShulkerCleanupHandler;
|
||||
import plugin.Listeners.ShulkerDragDupePrevention;
|
||||
import plugin.Listeners.ShulkerDragHandler;
|
||||
|
||||
@@ -31,6 +32,7 @@ public final class ShulkerStackingOG extends JavaPlugin {
|
||||
getServer().getPluginManager().registerEvents(new ShulkerDragDupePrevention(), this);
|
||||
getServer().getPluginManager().registerEvents(new ShulkerBoxHopperHandler(), this);
|
||||
getServer().getPluginManager().registerEvents(new ShulkerBoxMergeHandler(), this);
|
||||
getServer().getPluginManager().registerEvents(new ShulkerCleanupHandler(), this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user