Implement tool replacement for stack replacer
This commit is contained in:
parent
ad00a02261
commit
511e689e0c
@ -5,6 +5,8 @@ import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerItemBreakEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
@ -24,21 +26,75 @@ public class StackReplaceListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPlacedEvent(final BlockPlaceEvent event) {
|
||||
final ItemStack usedItemStack = event.getItemInHand();
|
||||
if (findAndMoveSimilarStack(event.getItemInHand(), event.getHand(), event.getPlayer().getInventory(), CompareFunc.defaultFunc()))
|
||||
logger.fine(LOG_PLUGIN_NAME + " Moved stack into empty hand for player " + event.getPlayer().getName());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerItemBreakEvent(final PlayerItemBreakEvent event) {
|
||||
final PlayerInventory inv = event.getPlayer().getInventory();
|
||||
final ItemStack used = event.getBrokenItem();
|
||||
|
||||
final EquipmentSlot slot;
|
||||
if (used.equals(inv.getBoots())) slot = EquipmentSlot.FEET;
|
||||
else if (used.equals(inv.getLeggings())) slot = EquipmentSlot.LEGS;
|
||||
else if (used.equals(inv.getChestplate())) slot = EquipmentSlot.CHEST;
|
||||
else if (used.equals(inv.getHelmet())) slot = EquipmentSlot.HEAD;
|
||||
else if (used.equals(inv.getItemInOffHand())) slot = EquipmentSlot.OFF_HAND;
|
||||
else if (used.equals(inv.getItemInMainHand())) slot = EquipmentSlot.HAND;
|
||||
else return; // No clue what broke
|
||||
|
||||
if (findAndMoveSimilarStack(used, slot, inv, CompareFunc.toolFunc()))
|
||||
logger.fine(LOG_PLUGIN_NAME + " Moved tool into empty hand for player " + event.getPlayer().getName());
|
||||
}
|
||||
|
||||
private boolean findAndMoveSimilarStack(
|
||||
final ItemStack usedItemStack,
|
||||
final EquipmentSlot target,
|
||||
final PlayerInventory inventory,
|
||||
final CompareFunc compareFunc) {
|
||||
if (usedItemStack.getAmount() == 1) {
|
||||
final PlayerInventory inv = event.getPlayer().getInventory();
|
||||
for (int i = Math.min(inv.getSize() - 1, MAX_MAIN_INV); i >= 0 ; --i) {
|
||||
final ItemStack checkStack = inv.getItem(i);
|
||||
if (i != inv.getHeldItemSlot() && usedItemStack.isSimilar(checkStack)) {
|
||||
for (int i = Math.min(inventory.getSize() - 1, MAX_MAIN_INV); i >= 0 ; --i) {
|
||||
final ItemStack checkStack = inventory.getItem(i);
|
||||
if (i != inventory.getHeldItemSlot() && compareFunc.isSimilar(usedItemStack, checkStack)) {
|
||||
// To prevent race-condition dupes, remove item before putting it in players hand
|
||||
inv.setItem(i, new ItemStack(Material.AIR, 0));
|
||||
inv.setItem(event.getHand(), checkStack);
|
||||
inventory.setItem(i, new ItemStack(Material.AIR, 0));
|
||||
inventory.setItem(target, checkStack);
|
||||
|
||||
logger.fine(LOG_PLUGIN_NAME + " Moved stack into empty hand for player " + event.getPlayer().getName());
|
||||
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Functional interface for determining when two item stacks are equivalent
|
||||
*
|
||||
* Note: The comparison should represent an equivalence relation (especially, it should be symmetric)
|
||||
*/
|
||||
private interface CompareFunc {
|
||||
boolean isSimilar(final ItemStack i1, final ItemStack i2);
|
||||
|
||||
static CompareFunc defaultFunc() { return ItemStack::isSimilar; }
|
||||
static CompareFunc toolFunc() {
|
||||
return (i1, i2) -> {
|
||||
final boolean isNull1 = i1 == null;
|
||||
final boolean isNull2 = i2 == null;
|
||||
|
||||
if (isNull1 || isNull2)
|
||||
return isNull1 == isNull2; // This should really never return true
|
||||
|
||||
final Material m1 = i1.getType();
|
||||
final Material m2 = i2.getType();
|
||||
|
||||
// If the material name has an underscore, it probably has material type alternatives
|
||||
if (m1.name().contains("_"))
|
||||
return m2.name().endsWith(m1.name().substring(i1.getType().name().lastIndexOf('_')));
|
||||
else
|
||||
return m2.equals(m1);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user