Creating player stats in a HashMap returning null?

Discussion in 'Plugin Development' started by GavinScience, May 25, 2020.

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

    GavinScience

    I am trying to create a sort of Hypixel Skyblock remake, and there are many stats that each player has to have. These include health, defense, crit chance, etc. I created base values that all players have, and then the normal values will be all item states added together. So the final product of stats will be item values combined plus base stats. When a player joins the server, their stats are defined in a player/integer hashmap, as shown below. The base values are put in for each player that joins, and the normal values will be dynamically updated, controlled by item tags. However, when I try to use these values in say an action bar text that displays the stats, I get an error saying that the player has no values in this hashmap (nullpointerexception). I need help to figure out why the hashmaps for each player are never added. Here is the class that adds the stats to each player...
    Code:
    public class SetStatsNew implements Listener {
       
        private Main main;
       
        public SetStatsNew(Main main) {
            this.main = main;
        }
       
        @EventHandler
        public void onJoin(PlayerJoinEvent e) {
            Player player = e.getPlayer();
           
            main.baseHealth.put(player, 100);
            main.baseDefense.put(player, 0);
            main.baseSpeed.put(player, 100);
            main.baseIntelligence.put(player, 0);
            main.baseStrength.put(player, 0);
            main.baseCritChance.put(player, 20);
            main.baseCritDamage.put(player, 50);
            main.mana.put(player, 100);
        }
    And here is the code that updates that action bar (null error is on line with the textcomponent)
    Code:
    public class ActionUpdater implements Listener {
    
        private Main main;
       
        public ActionUpdater(Main main) {
            this.main = main;
        }
       
        @EventHandler
        public void onJoin(PlayerJoinEvent e) {
            Player player = e.getPlayer();
           
            new BukkitRunnable() {
                @Override
                public void run() {
                    if (!player.isOnline()) {
                        cancel();
                    }
                    player.spigot().sendMessage(ChatMessageType.ACTION_BAR,
                    TextComponent.fromLegacyText("Health: " + main.baseSpeed.get(player).toString()));
                }
            }.runTaskTimer(main, 20L, 200L);
           
        }
    }
     
  2. Offline

    timtower Administrator Administrator Moderator

    @GavinScience The second onJoin runs before the first one.
    Use 1 event and call functions from there instead.
     
  3. Offline

    GavinScience

    Now I'm not getting any errors, but the Action Bar text isn't displaying. Does this have something to do with the legacy text I'm using?
     
  4. Offline

    timtower Administrator Administrator Moderator

    Does the method get called?
     
  5. Offline

    GavinScience

    Both the runnable and the hashmaps are in the same class I named joinlistener, and it also has a listener. I've attached code because I have not idea whats going on.
    Code:
    public class JoinListener implements Listener {
      
        private Main main;
      
        public JoinListener(Main main) {
            this.main = main;
        }
      
        @EventHandler
        public void onJoin(PlayerJoinEvent e) {
            Player player = e.getPlayer();
          
            main.baseHealth.put(player, 100);
            main.baseDefense.put(player, 0);
            main.baseSpeed.put(player, 100);
            main.baseIntelligence.put(player, 0);
            main.baseStrength.put(player, 0);
            main.baseCritChance.put(player, 20);
            main.baseCritDamage.put(player, 50);
            main.mana.put(player, 100);
          
            new BukkitRunnable() {
                @Override
                public void run() {
                    if (!player.isOnline()) {
                        cancel();
                    }
                    player.spigot().sendMessage(ChatMessageType.ACTION_BAR,
                    TextComponent.fromLegacyText("Health: " + main.baseHealth.get(player).toString()));
                }
            }.runTaskTimer(main, 20L, 20L);
    
        }
      
    }
    And here is the Main Class.
    Code:
    public class Main extends JavaPlugin {
      
        public HashMap<Player, Integer> health;
        public HashMap<Player, Integer> defense;
        public HashMap<Player, Integer> mana;
        public HashMap<Player, Integer> intelligence;
        public HashMap<Player, Integer> speed;
        public HashMap<Player, Integer> strength;
        public HashMap<Player, Integer> critDamage;
        public HashMap<Player, Integer> critChance;
        public HashMap<Player, Integer> effHealth;
        public HashMap<Player, Integer> baseHealth;
        public HashMap<Player, Integer> baseDefense;
        public HashMap<Player, Integer> baseIntelligence;
        public HashMap<Player, Integer> baseSpeed;
        public HashMap<Player, Integer> baseStrength;
        public HashMap<Player, Integer> baseCritDamage;
        public HashMap<Player, Integer> baseCritChance;
      
      
        @Override
        public void onEnable() {
            System.out.println("Player Stats successfully enabled!");
          
            Bukkit.getPluginManager().registerEvents(new JoinListener(this), this);
          
            //getCommand("stats").setExecutor(new StatsCommand(this));
        }
    }
     
  6. Offline

    timtower Administrator Administrator Moderator

    @GavinScience Do yourself a favor and make a class to store those values, then a HashMap<UUID, CustomStorageClass>
    Don't store player objects.
    Add a printline to the thing with sendMessage
     
  7. Offline

    GavinScience

    I'm confused as to what you mean when you want me to create a HashMap<UUID, StatStorage>. I have created a StatStorage with all of the hashmaps listed like in the main class, and when I add to them in the joinlistener class I use new StatStorage.baseHealth.put(player, 100). Am I doing this right? I'm sorry that I am not that good at using the spigot API, but thank you for helping me figure this out! I really appreciate it!
     
  8. Offline

    timtower Administrator Administrator Moderator

    @GavinScience Don't use so many maps, it is weird.
    Use 1 map that contains all data instead.
     
  9. Offline

    GavinScience

    Should I make a hashmap with HashMap<Player, List[Integer]> and I just have to define which indexes are which stat?
     
  10. Offline

    timtower Administrator Administrator Moderator

    @GavinScience Why would you do that? Why do you want something where you need to check what it is?
    Code:
    class Storage
    {
    Int value1;
    int value2
    }
     
Thread Status:
Not open for further replies.

Share This Page