1.16.5 Saving certain items on player's death

Discussion in 'Spigot Plugin Development' started by CROACH, Jul 6, 2021.

  1. Hi, I am currently working on Gadgets plugin and I need to make it so once players die, then they respawn but the gadgets that they could have in their inventory will
    1. not be included in the loot,
    2. will be given after respawn.

    This is code that i was using before
    Code (Java):
    private static Map<String, ItemStack> drops = new HashMap<String, ItemStack>();
        @EventHandler
        public void onDeath(PlayerDeathEvent e){

            e.getDrops().forEach(drop -> {
                if(drop.getItemMeta().getDisplayName().equals(ChatUtil.fixColors("&eHak z Liną")) || drop.getItemMeta().getDisplayName().equals(ChatUtil.fixColors("&f&lButy anioła"))){
                    drops.put(e.getEntity().getName(), drop);
                }
            });
        }
        @EventHandler
        public void onRespawn(PlayerRespawnEvent e){
            if(drops.containsKey(e.getPlayer().getName())){
                e.getPlayer().getInventory().addItem(drops.get(e.getPlayer().getName()));
                drops.remove(e.getPlayer().getName());
            }
        }
    but some time ago I discovered that when player have multiple gadgets in their inventory, only the first one (for example in slot 0, not 4) is working as intended.
     
  2. I mean you shouldn't be using itemname as a identifier in the first place,use PDC like a normal human that way is impossible to bug out an item
     
    • Like Like x 1
  3. It is impossible to get named item like this, and this doesn't answer my question
     
  4. 1) Change the HashMap's key to be the player itself and not their name (NEVER compare stuff by their name...)
    2) Change the HashMap's value to be a LIST of ItemStacks. When adding a player to it, first check if it already contains the player - it not, then put a new empty List in it, otherwise get the list and insert the item into it.
    3) As I said in #1: NEVER compare stuff by their name. Make the ItemStack have a special key in its PersistentDataContainer to identify if and which gadget it is.
    4) In the death function (onDeath) you need to remove the items (that will be readded after the respawn) from the event's drop list.
    5) Because of #2, change the respawn function (onRespawn) to add all the items in the list instead of a singular item.
     
    • Like Like x 2
  5. player's uuid is better
     
    • Agree Agree x 3
  6. The player itself is better since you don't need to search for the player each time.
    You use the UUID if you need to store the player in a database, otherwise it's an unnecessary step.
     
    • Agree Agree x 1
  7. so what happens when the player leaves
     
    • Like Like x 1
  8. Also those maps reset on restart/reload, Do you want that to happen? Might want to skip the death screen so players wont leave on deathscreen and not receive the items because of that, or alternatively save data somewhere
    Then player object wont work if player relogs,
    But in general nothing wrong with using player object, It might just memoryleak easier if you dont handle it correctly. I would use uuid
     
    #8 Zoltus, Jul 7, 2021
    Last edited: Jul 7, 2021
    • Like Like x 1
  9. I did it already but then how do I add an ItemStack to ItemStack[] ?
     
  10. List mate, not array.
    [] Is array.
     
    • Like Like x 1
  11. then how to do that?
     
  12. Code (Java):
    List<[some_type_idk_whatever]> list = new ArrayList<[some_type_idk_whatever]>();
    And to add values to it:
    Code (Java):
    list.add({some_value_of_that_type});
     
  13. You can just use the diamond operator for Java8+
    Code (Text):
    List<ItemStack> items = new ArrayList();
    Also you could do something like
    Code (Java):
    List<ItemStack> items = Arrays.asList(new ItemStack(Material.DIAMOND), new ItemStack(Material.BEDROCK));
     
    • Agree Agree x 1
  14. I'd avoid doing it this way since this creates an immutable list (unless you want it to be that way).
     
  15. Depends on what he wants to do (for those who dont know an immutable list is one where you cant add or take items away)
     
    • Like Like x 1
  16. But I need to also save a player
     
  17. He ment change
    Code (Java):
    private static Map<String, ItemStack> drops = new HashMap<String, ItemStack>();
    to
    Code (Java):
    private static Map<UUID, List<ItemStack>> drops = new HashMap<>();
     
    • Agree Agree x 1
  18. ^ and also String to UUID or if you prefer Player (i have no clue why) but be sure to avoid memory leaks
     
  19. And now how to retrieve this and give it to player on respawn?
    I made this code but it does not work and I am starting to give up
    Code (Java):
    public void onRespawn(PlayerRespawnEvent e){
            if(drops.containsKey(e.getPlayer())){
                for(item : drops.get(e.getPlayer())){
                    e.getPlayer().getInventory().addItem(item);

                }
                drops.get(e.getPlayer()).clear();

            }
        }
     
  20. Its not that complicated and we are here to help, so do not give up lol

    drops.get(e.getPlayer()) returns the value of the hashmap, that is the list of ItemStack. So now when you are clearing that list its a bit useless. What you should be doing is removing the player key from the hashmap.