Hello! I tried to make it, that dispensers can place blocks, and it worked (relativile) well, but now i have a problem. The blocks are being placed, and the 1 item removes, but if only 1 item is in the dispenser, nothing happenes. Here the (I think) most important code parts: Code (Text): //Test if it's a block if (e.getItem().getType().getId() < 256) { //Get dispenser Block b = e.getBlock(); Dispenser disp = (Dispenser) b.getState().getData(); BlockFace face = (disp.getFacing()); //Get placed-block location Location loc = b.getLocation(); loc.add(face.getModX(), face.getModY(), face.getModZ()); Code (Text): //Cancel event & get inventory e.setCancelled(true); Block block = e.getBlock(); org.bukkit.block.Dispenser dispenser = (org.bukkit.block.Dispenser) block.getState();; Inventory inv = dispenser.getInventory(); ItemStack[] items = inv.getContents(); Code (Text): //Get random slot //Test if the inventory is empty if (items == null || (items[0] == null && items[1] == null && items[2] == null && items[3] == null && items[4] == null && items[5] == null && items[6] == null && items[7] == null && items[8] == null)) return; //get slot int slot = (int) (Math.random()*9); while (items[slot] == null) { slot = (int) (Math.random()*9); } Code (Text): //Placing Block loc.getWorld().getBlockAt(loc).setType(stack.getType()); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); //UpdatingBlock Material bak = loc.getWorld().getBlockAt(loc.add(0, 1, 0)).getType(); byte bakb = loc.getWorld().getBlockAt(loc).getData(); loc.getWorld().getBlockAt(loc).setType(Material.AIR); loc.getWorld().getBlockAt(loc).setType(Material.GRASS); loc.getWorld().getBlockAt(loc).setType(bak); loc.getWorld().getBlockAt(loc).setData(bakb); Code (Text): //Remove 1 item if (stack.getAmount() != 1) { stack.setAmount(stack.getAmount() - 1); dispenser.getInventory().setItem(slot, stack); } else { //Tried different things here: This, set Slot to air, set slot to null stack.setAmount(stack.getAmount() - 1); dispenser.getInventory().setItem(slot, stack); } Spoiler: Whole code (if someone want to see it) package blockplacer.main; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockDispenseEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.material.Dispenser; import org.bukkit.plugin.java.JavaPlugin; public class BlockPlacer extends JavaPlugin implements Listener { @Override public void onEnable() { Bukkit.getPluginManager().registerEvents(this, this); } @SuppressWarnings("deprecation") @EventHandler(priority = EventPriority.HIGHEST) public void BlockDispense(BlockDispenseEvent e) { if (e.getItem().getType().getId() < 256 || e.getItem().getType() == Material.POTATO_ITEM || e.getItem().getType() == Material.CARROT_ITEM || e.getItem().getType() == Material.SEEDS || e.getItem().getType() == Material.PUMPKIN_SEEDS || e.getItem().getType() == Material.MELON_SEEDS || e.getItem().getType() == Material.BEETROOT_SEEDS || e.getItem().getType() == Material.SAPLING) { Block b = e.getBlock(); Dispenser disp = (Dispenser) b.getState().getData(); BlockFace face = (disp.getFacing()); Location loc = b.getLocation(); loc.add(face.getModX(), face.getModY(), face.getModZ()); if (!loc.getWorld().getBlockAt(loc).getType().isSolid() && !(loc.getWorld().getBlockAt(loc).getType() == Material.RAILS) && !(loc.getWorld().getBlockAt(loc).getType() == Material.POWERED_RAIL) && !(loc.getWorld().getBlockAt(loc).getType() == Material.DETECTOR_RAIL) && !(loc.getWorld().getBlockAt(loc).getType() == Material.ACTIVATOR_RAIL) && !(loc.getWorld().getBlockAt(loc).getType() == Material.POTATO) && !(loc.getWorld().getBlockAt(loc).getType() == Material.CARROT) && !(loc.getWorld().getBlockAt(loc).getType() == Material.PUMPKIN_STEM) && !(loc.getWorld().getBlockAt(loc).getType() == Material.MELON_STEM) && !(loc.getWorld().getBlockAt(loc).getType() == Material.BEETROOT_BLOCK) && !(loc.getWorld().getBlockAt(loc).getType() == Material.CROPS) && !(loc.getWorld().getBlockAt(loc).getType() == Material.SAPLING)) { e.setCancelled(true); Block block = e.getBlock(); org.bukkit.block.Dispenser dispenser = (org.bukkit.block.Dispenser) block.getState();; Inventory inv = dispenser.getInventory(); ItemStack[] items = inv.getContents(); /*if (items == null || (items[0] == null && items[1] == null && items[2] == null && items[3] == null && items[4] == null && items[5] == null && items[6] == null && items[7] == null && items[8] == null)) { if (e.getItem() != null) { items[0] = e.getItem(); } }*/ if (items == null || (items[0] == null && items[1] == null && items[2] == null && items[3] == null && items[4] == null && items[5] == null && items[6] == null && items[7] == null && items[8] == null)) return; int slot = (int) (Math.random()*9); while (items[slot] == null) { slot = (int) (Math.random()*9); } ItemStack stack = items[slot]; if (stack.getType() == Material.POTATO_ITEM) { loc.getWorld().getBlockAt(loc).setType(Material.POTATO); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); } else if (stack.getType() == Material.CARROT_ITEM) { loc.getWorld().getBlockAt(loc).setType(Material.CARROT); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); } else if (stack.getType() == Material.SEEDS) { loc.getWorld().getBlockAt(loc).setType(Material.CROPS); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); } else if (stack.getType() == Material.PUMPKIN_SEEDS) { loc.getWorld().getBlockAt(loc).setType(Material.PUMPKIN_STEM); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); } else if (stack.getType() == Material.MELON_SEEDS) { loc.getWorld().getBlockAt(loc).setType(Material.MELON_STEM); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); } else if (stack.getType() == Material.BEETROOT_SEEDS) { loc.getWorld().getBlockAt(loc).setType(Material.BEETROOT_BLOCK); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); } else if (stack.getType() == Material.SAPLING) { loc.getWorld().getBlockAt(loc).setType(Material.SAPLING); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); } else { loc.getWorld().getBlockAt(loc).setType(stack.getType()); loc.getWorld().getBlockAt(loc).setData((byte) stack.getDurability()); } Material bak = loc.getWorld().getBlockAt(loc.add(0, 1, 0)).getType(); byte bakb = loc.getWorld().getBlockAt(loc).getData(); loc.getWorld().getBlockAt(loc).setType(Material.AIR); loc.getWorld().getBlockAt(loc).setType(Material.GRASS); loc.getWorld().getBlockAt(loc).setType(bak); loc.getWorld().getBlockAt(loc).setData(bakb); if (stack.getAmount() != 1) { stack.setAmount(stack.getAmount() - 1); dispenser.getInventory().setItem(slot, stack); } else { stack.setAmount(stack.getAmount() - 1); dispenser.getInventory().setItem(slot, stack); } } } } } I have an Idea why it could not work: If I put 4 items in the dispenser, activate it and make at the start of the event System.out.print(stack.getAmount()), it says 3. And if make a sysout for the slot that I generated randomly, it says it right. But if I have only 1 item, it always says: "Slot:0, amount:1". Just for the case that can help you I hope someone can help me! Thanks!
I've had the same problem with my plugin when handling with dispenser and tnt. You need to clear the inventory (If and ONLY if one item remain inside the dispenser inventory) with a 1tick delay, since during the event when is cancelled, the inventory is not updated and does not see the item change
Ok, thanks. That's how I did it: Code (Text): //the variables items, itemcount, slot & stack are already defined if (stack.getAmount() != 1) { stack.setAmount(stack.getAmount() - 1); dispenser.getInventory().setItem(slot, stack); } else { Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { @Override public void run() { itemcount = 0; for (int i = 0; i < 9; i++) { if (items[i] != null) { itemcount+=items[i].getAmount(); } } if (itemcount == 1) { dispenser.getInventory().clear(); } else { stack.setAmount(stack.getAmount() - 1); dispenser.getInventory().setItem(slot, stack); } } }, 1); } That worked, exeptly with 1 issue: The removing now works, except if there are 2 items, that are not stacked. I have an idea why: Minecraft thinks, that the item is dispensed and removes it from the dispenser item list. If the items are stacked, it's no problem, because then it just removes one. But if the items are not stacked, it thinks that, because one item isn't anymore in list, there is only one item in the dispenser and clears the inventory. Now i made a little fix: Code (Text): boolean isMissing = true; int freeslot = 0; for (int i = 0; i < 9; i++) { ItemStack is = items[i]; if (is != null) { if (is.getType().equals(e.getItem().getType())) { if (is.getDurability() == e.getItem().getDurability()) { isMissing = false; } } } else { freeslot = i; } } if (isMissing) items[freeslot] = e.getItem(); The fix tests goes through all items in the inv, and 1. checks if there not null if so, it checks 2. if the item is the same type as that one that would normally dispensed and 3. checks for the same durability if that is the case, then i know that the item is in the inventory. And if not, I add the Item to inventory list (not the dispenser inventory, just to the list that the inv won't be cleared) And with this fix EVERYTHING except 1 little thing works: If there are 2 items of the same type but not stacked, because it thinks that it is already inside. So, any idea how I can fix this, or another way? I would have an idea: Just make a method that stacks the items. But, if it is possible, i would be happy for a better solution. Thanks for your help & I hope you have an Idea!
The way i did that, instead take the item that is being dispensed, take the first item in the inventory that fits your needs (Using a for loop and the getItem(Integer) method). If the inventory was empty, then i was moved to the item being dispensed and check if it's the one i need. This was the only i could fix it
So, here the code i use for check which item use (cItem is my item manager, so the method you use is the one i use to fetch the name in the config) Spoiler: Part1 Code (Text): for(slot=0;slot<i.getSize();slot++) { if(i.getItem(slot)!=null) { empty=false; if(cItem.getByItem(i.getItem(slot))!=null) { item=i.getItem(slot); break; } } } if(item==null) { if(cItem.getByItem(e.getItem())==null && empty) { return; } item=e.getItem(); } And here the code to how i manage to remove the item or clear the inventory Spoiler: Part 2 Code (Text): if(empty) { if(use!=1) { return; } new BukkitRunnable() { @Override public void run() { d.getInventory().clear(); } }.runTaskLater(pl, 1); } else { ItemStack tItem = i.getItem(slot); if(tItem.getAmount()+1<use) { return; } tItem.setAmount(tItem.getAmount()-use); i.setItem(slot, tItem); }