1.14.4 Inventory Events not firing

Discussion in 'Spigot Plugin Development' started by SeanTMG, Jan 10, 2020.

  1. Hello all,

    I've been trying for an hour now to get some events working, to no avail.

    What I want to do is sync everyone's inventory across the server. Yet some things I can't get working.

    1. InventoryMoveItemEvent does not fire at all.
    2. I can't get EntityPickupItemEvent working,
    Code (Java):
    ((Player) event.getEntity()).getInventory().getContents()
    Doesn't add the picked up item.
     
  2. md_5

    Administrator Developer

    Read the docs for that event, it probably doesn't do what you think it does.
    Most events in Bukkit fire before the action happens so they can be cancelled.
    Look what other methods the event provides.
     
  3. InventoryMoveItemEvent is fired when a hopper or minecart etc. transfers items not when a player clicks on items in chests.

    > Pls show some code for the EntityPickupItemEvent.

    > And this shouldn't add picked up items. Pls show some code.
     
  4. MrGeneralQ

    MrGeneralQ Previously qintinator
    Supporter

    Did you register the event in your onEnable()?
     
    • Agree Agree x 1
    • Friendly Friendly x 1
  5. SOURCE: "https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/inventory/InventoryClickEvent.html"

    public class InventoryClickEvent
    extends InventoryInteractEvent
    This event is called when a player clicks a slot in an inventory.
    Because InventoryClickEvent occurs within a modification of the Inventory, not all Inventory related methods are safe to use.

    The following should never be invoked by an EventHandler for InventoryClickEvent using the HumanEntity or InventoryView associated with this event:

    To invoke one of these methods, schedule a task using BukkitScheduler.runTask(Plugin, Runnable), which will run the task on the next tick. Also be aware that this is not an exhaustive list, and other methods could potentially create issues as well.
     
  6. Inventory events don't act the same way if you are in creative mode. So make sure you are not in creative mode when you test. Not sure if thats your problem but it bites me in the bum every time i turn around it seems.

    edit: When creative mode is open all clicktypes are this:
    CREATIVE
    Any action done with the Creative inventory open.
     
  7. Sorry for not responding to this for a while, had a lot of stuff come up.

    Code (Java):
        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
            System.out.println(event.getAction());
            switch (event.getAction()) {
                case PLACE_ALL:
                    for (Player p : Bukkit.getOnlinePlayers())
                        p.getInventory().setContents(event.getWhoClicked().getInventory().getContents());
                    break;
            }
        }
    With this code it's extremely buggy and has a ton of weird behavior, for example sometimes i'll place something in my inventory and it'll be invisible until I click the slot again and I'll be holding it. Sometime's it'll just completely clear the inventory altogether.
     
  8. Life, it happens. Nuff said.

    Couple of things; Shouldn't it be InventoryAction.PLACE_ALL ? Where is the event.setCancelled(true); return; Don't let your code keep running once you have made your modifications.

    Edit: Ok yea when you have eclipse fill in the cases for you it just does PLACE_ALL, guess I have been being anal about that.
     
  9. @Tarluin For Switch statements you use have to use simply PLACE_ALL, in other circumstances you would need yo use the full InventoryAction.PLACE_ALL. His code is correct here. (Seems like you have an edit explaining this now)

    @SeanTMG As for your items being wonky, what you want to do is actually kind of tricky.
    You can left click to put an item on your cursor, shift click, alt click, shift right click, alt right click etc.

    If I remember correctly PLACE_ALL is when you shift click right? That is when all items are placed from one inventory to another, not exactly sure though.

    In any case, this event is happening before the inventory has actually changed. It has happened right before so that you can modify or stop the change all together.

    If you leave the code simply the way you have it, but scheduled the inventory change to happen one tick from then, that will be setting all the inventories to what has happened after the event.
    I recommend you try that, but due to all the inventory manipulations you can make, you might need to add in some more.
     
  10. Thanks :)

    Remember if your doing modification manually like this you need to cover all the loose ends and cancel the event or it will do both your manipulation and its normal behavior.

    Edit: and if a player has an inventory open while this is being done I'm not sure if it would update properly or not.
     
  11. The event should not be canceled. If you are canceling the event the inventory will just be frozen the same all the time.
    I'm not sure if that is what is supposed to be done, but it seems like they want changes to happen, (so do not cancel the event or they will not happen) and then to sync all the other players inventories to be the same.
    Let the change happen, then update the inventories after it has one server tick later.
     
    #11 ForbiddenSoul, Jan 11, 2020
    Last edited: Jan 11, 2020
  12. @ForbiddenSoul Good Idea, didn't think of that, I did think it might be because it's grabbing the inventory before it gets updated but I never had the idea to just delay it, it works perfectly!

    For anyone wondering or people who may need it, here's the full code:

    Code (Java):
        @EventHandler
        public void onEntityPickupItem(EntityPickupItemEvent event) {
            Player player = (Player) event.getEntity();
            Bukkit.getScheduler().scheduleSyncDelayedTask(pl, () -> {
                for (Player p : Bukkit.getOnlinePlayers())
                    p.getInventory().setContents(player.getInventory().getContents());
            }, 1L);
        }

        @EventHandler
        public void onPlayerDropItem(PlayerDropItemEvent event) {
            Bukkit.getScheduler().scheduleSyncDelayedTask(pl, () -> {
                for (Player p : Bukkit.getOnlinePlayers())
                    p.getInventory().setContents(event.getPlayer().getInventory().getContents());
            }, 1L);
        }

        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
            Bukkit.getScheduler().scheduleSyncDelayedTask(pl, () -> {
                switch (event.getAction()) {
                    case PLACE_ALL:
                    case MOVE_TO_OTHER_INVENTORY:
                        for (Player p : Bukkit.getOnlinePlayers())
                            p.getInventory().setContents(event.getWhoClicked().getInventory().getContents());
                        break;
                }
            }, 1L);
        }