Solved How to check if a players inventory is full?

Discussion in 'Plugin Development' started by DinoZauruZ, Jan 31, 2015.

Thread Status:
Not open for further replies.
  1. Offline

    DinoZauruZ

    So as the title says I want to check if a players inventory is full, it's for a plugin I'm making that clears drops when a player breaks a block and give it to them directly. So I want them to know that their inventory is full I will supply code bellow.

    Code:
    @EventHandler
        public void BlockBreak(BlockBreakEvent e) {
           
           
            for(ItemStack item : e.getBlock().getDrops()){
                e.getPlayer().getInventory().addItem(item);
            }
            e.setCancelled(true);
            e.getBlock().setType(Material.AIR);
        }
    }
    
    It works but when the players inventory is full, I want them to get a message I found other threads but didn't quite understand them. So please some help, I have no idea how to check. Thanks.
     
  2. Offline

    Skionz

    Inventory#firstEmpty returns -1 if the inventory is full.
     
    Konato_K likes this.
  3. Offline

    DinoZauruZ

    I don't really understand that sorry I got this? but I can't use it as a boolean since I get an error, Sorry for this I'm new to bukkit API and coding in general. @Skionz

    Code:
    Code:
    @EventHandler
        public void BlockBreak(BlockBreakEvent e) {
          
            e.getPlayer().getInventory().firstEmpty();
            for(ItemStack item : e.getBlock().getDrops()){
                e.getPlayer().getInventory().addItem(item);
            }
            e.setCancelled(true);
            e.getBlock().setType(Material.AIR);
        }
    }
    
     
  4. Offline

    Skionz

  5. Offline

    DinoZauruZ

    I'm not that bad, thanks anyway. But still? @Skionz
     
  6. Offline

    Skionz

    @DinoZauruZ
     
  7. Offline

    leon3001

    @DinoZauruZ Okay, what is
    Code:
    e.getPlayer().getInventory().firstEmpty();
    supposed to do?
     
  8. Offline

    DinoZauruZ

    Check for the first empty slot I guess? @leon3001
     
  9. Offline

    leon3001

    @DinoZauruZ Yeah, that's what it does but you don't do anything with the return value of the method. :p
     
  10. Offline

    SuperOriginal

    @leon3001 Obviously you do... If you read Skionz's posts.
     
    teej107 likes this.
  11. Offline

    leon3001

    @SuperOriginal Okay, did you intend to tag me? :) Because then, I don't really understand what you're trying to say. ^^"
     
  12. Offline

    DinoZauruZ

    Code:
    @EventHandler
        public void BlockBreak(BlockBreakEvent e) {
          
            if(!(e.getPlayer().getInventory().firstEmpty() == -1)){
          
            for(ItemStack item : e.getBlock().getDrops()){
                e.getPlayer().getInventory().addItem(item);
                }
            }
            e.setCancelled(true);
            e.getBlock().setType(Material.AIR);
    I'm gonna try that, Don't know if it's right.

    EDIT:
    I'm adding Else too.
     
  13. Offline

    SuperOriginal

    @leon3001 oh I misinterpreted your post. I thought you were saying that that method in general is useless.
     
    leon3001 likes this.
  14. Offline

    DinoZauruZ

    Okay. So now it works but the player gets the message when there is no slot avaible. I want it to still work, such as they have dirt in their inventory fully and one stack is 63 they break one and it will give them it. But now if they try that they just get the message.
    Code:
    Code:
    @EventHandler
        public void BlockBreak(BlockBreakEvent e) {
          
            if(!(e.getPlayer().getInventory().firstEmpty() == -1)){
          
            for(ItemStack item : e.getBlock().getDrops()){
                e.getPlayer().getInventory().addItem(item);
                }
            }else{
                e.getPlayer().sendMessage(RED + "Your inventory is full.");
            }
            e.setCancelled(true);
            e.getBlock().setType(Material.AIR);
        }
    }
    
    EDIT:
    PS: Sorry for the bad english very very tired.
     
  15. You can also just use != instead of !(... == -1) :)
     
  16. Offline

    DinoZauruZ

    Hmmmm @Lionhard yeh I'll do that.

    Code:
    Code:
    @EventHandler
        public void BlockBreak(BlockBreakEvent e) {
           
            if((e.getPlayer().getInventory().firstEmpty() != -1)){
           
            for(ItemStack item : e.getBlock().getDrops()){
                e.getPlayer().getInventory().addItem(item);
                }
            }else{
                e.getPlayer().sendMessage(RED + "Your inventory is full.");
            }
            e.setCancelled(true);
            e.getBlock().setType(Material.AIR);
        }
    }
    
     
  17. @DinoZauruZ And you also have one additional, not needed () brackets in the same condition. :))
    And by the way, I'm not sure, but I think when you cancel the event, it won't continue the code anymore, so e.getBlock().setType(Material.AIR); might not be accessed anymore. I really don't know.
    EDIT: This works. :)

    Also that "RED" is wrong, it is supposed to be ChatColor.RED.

    So now this code
    Code:
        @EventHandler
        public void BlockBreak(BlockBreakEvent e) {
      
            if (e.getPlayer().getInventory().firstEmpty() != -1){
      
                for(ItemStack item : e.getBlock().getDrops()){
                    e.getPlayer().getInventory().addItem(item);
                }
           
            } else {
                e.getPlayer().sendMessage(ChatColor.RED + "Your inventory is full.");
            }
       
            e.setCancelled(true);
            e.getBlock().setType(Material.AIR);
        }
    works perfectly how you want it to work.

    But the only thing you need to keep in mind, items that drop multiple items, you are going to run into "Your inventory is full there".
    Also, if your inventory is totally full, but you have one "unfinished" stack of dirt for example, with 36 items of dirt. A stack can get up to 64 items, right? So it should work, but no it doesn't. Because you check if there is an TOTALLY empty slot, which isn't.

    EDIT: Creative Mode players now also get items, you need to add another check if the player is in survival (or any other modes you want) mode and then give them the items. Unless you also want creatives to get the items.
     
    Last edited: Feb 1, 2015
  18. Offline

    DinoZauruZ

    @Lionhard since i
    import static org.bukkit.ChatColor.*;
    I can use RED instead of ChatColor.RED

    Back to the plugin, if a player has full inventory and one stack 60 dirt they break one dirt and they get "Your inventory is full."
    And they don't get it at all :/ so I need to check if the ?players inventory is full but not the block they break?
    Hard to explain but try and thanks for respond trying to figure out all night.
     
  19. Offline

    caderape

    something like this may be ? if the inventory is full, loops all the item of the inventory and check if u can add this. And when its full, you get the full message and drop the item at the player location.
     
  20. Offline

    DinoZauruZ

    Code:
    @EventHandler
        public void BlockBreak(BlockBreakEvent e) {
           
            Player p = e.getPlayer();
           
            if(e.getPlayer().getInventory().firstEmpty() == -1){
                ItemStack add = (ItemStack) e.getBlock();
               
                try{
                    for (ItemStack item : p.getInventory().getContents()) {
                        if(item.getType() == add.getType() && item.getAmount() != 64) {
                            int space = 64 - item.getAmount();
                            if(add.getAmount() > space){
                                add.setAmount(add.getAmount() - space);
                                item.setAmount(64);
                                }
                        }else{
                            item.setAmount(item.getAmount() + add.getAmount());
                            e.setCancelled(true);
                            e.getBlock().setType(Material.AIR);
                            for(ItemStack items : e.getBlock().getDrops()) {
                                e.getPlayer().getInventory().addItem(items);
                            return;
                        }
                    }
                }
                    }catch (Exception e2) {
                        p.sendMessage(RED + "Your inventory is full.");
                }
            }
        }
    }
            
    Well this doesn't really work not sure if it's right but I tried your method @caderape but I just get loads of errors :/ help?
     
  21. Offline

    caderape

    @DinoZauruZ i said something like this, not it will be perfect :p You have to check before to get type if the item is null or no first.

    And the else is wrong placed.
    if(add.getAmount()> space){
    } else {
    }

    Edit!
    You may have an error with { } in your code, may be you missed one. It doesnt look fine.
    Anyway, i didnt noticed, but it's called for a block breack, so you can simplify the code, cuz it will be only an amount of 1 everytime.
     
    Last edited: Feb 1, 2015
  22. @DinoZauruZ OK, tbh I didn't know about the static import, but why? Anyways, that's off topic again.

    Exactly that thing with the stacks of dirt is what I have told. I don't want to spoonfeed you, as you won't learn anything that way, so I will explain you the steps you need to do as soon as I get home.
     
  23. Offline

    DinoZauruZ

  24. @DinoZauruZ Whooaahhh... After 4 and a half hours I finished this stupid simple code... I had myself big trouble doing that. :D I will "spoonfeed" you in this thread, but I will PM you with a description on what everything does. Here is the explanation with the final code.
    In order to achieve the best out of my horrible explanation skillz, let's split the code into 3 parts.
    Parts (open)

    Code:
    @EventHandler
    public void BlockBreak(BlockBreakEvent e) {
        if (e.getPlayer().getInventory().firstEmpty() != -1){
            // Part 1
        } else {
            // Part 2
        }
        // Part 3
    }

    Now, Part 1 is easy. All we do here is:
    • Check if there are free slots in the player's inventory.
    • Iterate through all the drops the block has.
    • Finally, add the item/s to the player's inventory.
    Part 1 (open)

    This goes at the beginning of the BlockBreakEvent.
    Code:
    if (e.getPlayer().getInventory().firstEmpty() != -1){
        for(ItemStack item : e.getBlock().getDrops()){
            e.getPlayer().getInventory().addItem(item);
        }
    }
    Roughly translated: If you find an empty slot, go through all the drops and give it to the player.
    Part 2 is directly "attached" to part 1, and won't work without this.

    Now, in part 2 the tricky code goes on. As in bukkit I couldn't find suitable methods to check for an 'not-full' stack of a given item, we need to use our own way to do so. What we do in here is:
    • 'Check' (Logically, it is run because the condition in the if-statement wasn't met.) if there are NO free slots in the player's inventory.
    • Iterate through all the drops the block has, again.
    • Use a for-loop to create an 'id', used to go through every slot in the inventory. (More about this later.)
    • Check if the amount of the drop would fit into the stack.
    • Check if both the items in the current slot and the drop are same.
    • Add the drop into the player's inventory.
    • Break the loop. (More about this later.)
    • If the above code wasn't reached (Meaning no appropriate slot for the item found.), and the slot ID is the last one, we inform the player that his/her inventory is full. (More about this later, too.)
    Part 2 (open)

    This is attached right behind Part 1.
    Code:
    else {
        for(ItemStack item : e.getBlock().getDrops()){
            for (int i=0; i<35; i++) {
                if (e.getPlayer().getInventory().getItem(i).getAmount()+item.getAmount()<=64) {
                    if (e.getPlayer().getInventory().getItem(i).getType().equals(item.getType())) {
                        e.getPlayer().getInventory().addItem(item);
                        break;
                    }
                }
                if (i==34) {
                    e.getPlayer().sendMessage(ChatColor.RED + "Your inventory is full.");
                }
            }
        }
    }
    Roughly translated: If you don't find an empty slot, go through all the drops and do this for each drop: Run through all slots in the player's inventory and check if the drop (amount) would fit into the stack in the current slot and if the items are the same. If yes, add the drop into the player's inventory and break the loop (Stop it from doing more, otherwise it could give you multiple items.). If not, go to the next slot. If the drop didn't match any items and the slot reached the last slot (slot 35), inform the player that his/her inventory is full.

    In a more programatically way:
    Code:
    for (int i=0; i<35; i++) {
        // Code
    }
    What this does is, it creates a variable i with the starting value 0. The code is going to start running. And at the end of the whole loop, it increases the variable i by 1. This will be repeated as long as the variable i is lower than 35. Why 35? Because the number of slots a normal player inventory has 35 slots.
    Code:
    if (e.getPlayer().getInventory().getItem(i).getAmount()+item.getAmount()<=64) {
        // Code
    }
    This checks if the item would even fit into a stack. How? Well, it get's the amount of the current item in the slot the iteration is currently at and adds the amount of the dropped item to it. It checks if this number is lower or equal to 64, if yes, it fits into it. So for example if the iteration is currently at slot 3, where you have 54 logs of wood. If you break another log, you would get 1, so the final number would be 55, which is lower than 64 and so the item would fit into a stack. If you would have 63 logs and you would break another log, you would have 64, this item is the last item that would fit into the stack, that's why the = sign is very important.
    Code:
     if (e.getPlayer().getInventory().getItem(i).getType().equals(item.getType())) {
        // Code
    }
    This is easy, it just checks if the item at the current slot is equal to the dropped item.
    Code:
    break;
    Now the break; function is interesting. Let's explain this on another example.
    Let's say you would have your inventory full with this bar:
    [​IMG]
    It would either not work, or give you multiple items, as it would go to the 3rd slot, check if it dirt, if yes, it would add one to it, BUT it wouldn't break, so it would just continue until it reaches slot 5 and add another dirt to it and so on.
    It would at the end also send you a message saying "Your inventory is full.", because when it reaches the last slot, it runs the check if i is 34.
    So you can see, this plays a big role. Now we already spoke about the last check "if i is 34". Let's talk a bit more about this.
    Code:
     if (i==34) {
        e.getPlayer().sendMessage(ChatColor.RED + "Your inventory is full.");
    }
    Without the break; function, this would happen everytime, because the for loop would always reach slot 34 (Because it checks the whole inventory.). But because we have the break; function, this get's only run when the break; function won't run. And when does that happen? You're right - when there is no matching item! So now you have a full inventory and no matching item where to add the dropped item. Why not just inform the player about it?

    Now let's talk about the last, part 3 and one additional required step.
    What we just do here is:
    • Prevent the block from dropping the the regular vanilla drops.
    • Remove the block (Changing it to AIR - Nothing.).
    Part 3 (open)

    This comes behind the statements form Part 1 and Part 2.
    Code:
    e.setCancelled(true);
    e.getBlock().setType(Material.AIR);
    Roughly translated: Prevent the block from dropping items in the vanilla way and remove the block.
    The last, required and very important step is - register your event.
    You do that very simply by running this code in your onEnable() method in the main class, for example.
    Code:
    this.getServer().getPluginManager().registerEvents(<Listener>, <Plugin>);
    But this isn't part of this 'explanation' anymore and you should know that already. It is just a notification to spare you some time trying to figure out why the code doesn't work.

    If you are one of the lazy guys out there, here is the final code, ready for your copy & paste. :p But don't blame me if you don't understand it...
    Final Code (open)

    Code:
    @EventHandler
        public void BlockBreak(BlockBreakEvent e) {
            if (e.getPlayer().getInventory().firstEmpty() != -1){
                for(ItemStack item : e.getBlock().getDrops()){
                    e.getPlayer().getInventory().addItem(item);
                }
       
            } else {
                for(ItemStack item : e.getBlock().getDrops()){
                    for (int i=0; i<35; i++) {
                        if (e.getPlayer().getInventory().getItem(i).getAmount()+item.getAmount()<=64) {
                            if (e.getPlayer().getInventory().getItem(i).getType().equals(item.getType())) {
                            
                                e.getPlayer().getInventory().addItem(item);
                                break;
                            }
                        }
                        if (i==34) {
                            e.getPlayer().sendMessage(ChatColor.RED + "Your inventory is full.");
                        }
                    }
                }
            }
    
            e.setCancelled(true);
            e.getBlock().setType(Material.AIR);
        }


    Try it out and if it works, mark the thread as solved and consider giving me a like. :)

    Now, of course there are multiple ways to achieve the same goal - some might be better, some might not. But that's how it works during programming, there will always be multiple ways of doing the same thing.

    Another note is, this code of course isn't perfect. I just tried to quickly finish it. For example, if you use doors (which can't be stacked to 64, it most likely will result in errors, etc.), so just play around a bit with the code. A fix for this would be something like:
    Code:
    item.getMaxStackSize();
    Feel free to improve the code and play around with it.

    EDIT: Explanation added.
    It took me really much time to do that explanation, so I hope it was worth it and some of you find it useful! :)
     
    Last edited: Feb 2, 2015
    DinoZauruZ likes this.
  25. Offline

    DinoZauruZ

    Thanks ALOT! :) Thanks everyone but especially @Lionhard I will read through the pm u sent me. Thanks.
     
  26. Offline

    timtower Administrator Administrator Moderator

  27. Offline

    DinoZauruZ

    Explaining of code, @timtower very nice of him.
     
  28. Offline

    SuperOriginal

    @DinoZauruZ @Lionhard Would probably be best to have the PM inserted here so future viewers can see the explanation behind his code.
     
    Konato_K and Lionhard like this.
  29. @timtower Because it's a bunch of code and I was tired to put it all into this thread. I would have to spend a lot more time into writing it properly, so everyone understands. In the conversation, he can anytime ask me if he doesn't understand something. Additionally, if anyone would like me to explain it too, they can PM me for an explanation too, I can just invite them to the conversation or resend it.

    EDIT: @SuperOriginal That's probably a better Idea. I will do it tomorrow though, I will write it a bit better than in the PM. :D I'm bad at explaining. :S
     
  30. Offline

    timtower Administrator Administrator Moderator

    Pretty much why threads exists though.
    @Lionhard Please add it in here as well ;)
    Thank you for your explanation.
     
Thread Status:
Not open for further replies.

Share This Page