Solved NullPointerException when trying to removePlayer from BossBar?

Discussion in 'Spigot Plugin Help' started by luiskeniosis, Jan 18, 2020.

  1. I'm trying to make a bossbar that counts down the cooldown of abilities in a game mode i'm trying to make. The code works, and the bossbar appears for the player, but I get a NullPointerException when trying to remove the bossbar from the player.

    notifications.getCooldownBar().removeAll();
    is the line of code that gives me the exception.

    Code (Text):
    package lucien.HardcoreGames.game;

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.UUID;
    import java.util.concurrent.ConcurrentHashMap;

    import org.bukkit.Bukkit;
    import org.bukkit.NamespacedKey;
    import org.bukkit.boss.BarColor;
    import org.bukkit.boss.BarStyle;
    import org.bukkit.boss.BossBar;
    import org.bukkit.entity.Player;
    import org.bukkit.scheduler.BukkitRunnable;

    public class Cooldowns {
        public static ConcurrentHashMap<UUID, Integer> cooldowns = new ConcurrentHashMap<UUID, Integer>();
        public static List<Player> hasBarShown = new ArrayList<Player>();

        public static void startCooldownTimer() {
        new BukkitRunnable() {
            @Override
            public void run() {
            //If there are players with cooldowns
            if(!cooldowns.isEmpty()) {
                //For every player with a cooldown
                for(UUID uuid : cooldowns.keySet()) {
                //Save their remaining cooldown time
                int timeleft = cooldowns.get(uuid);
                //Save the player
                Player player = Bukkit.getPlayer(uuid);
                NotificationManager notifications = new NotificationManager();
                NamespacedKey barNameKey = new NamespacedKey(Main.plugin, "cooldownBar");
                //If the player has a cooldown
                if(timeleft > 0) {
                    //Remove 1 second from their cooldown
                    cooldowns.put(uuid, timeleft - 1);
                    Bukkit.broadcastMessage("" + timeleft);
                    if(!hasBarShown.contains(player)) {
                    hasBarShown.add(player);
                    notifications.createCooldownBar(barNameKey, "test", BarColor.YELLOW, BarStyle.SOLID);
                    BossBar cooldownBar = notifications.getCooldownBar();
                    cooldownBar.addPlayer(player);
                    }
                }
                //If the player dosen't have a cooldown
                else {
                    //Remove them from the list of players with a cooldown
                    cooldowns.remove(uuid);
                    Bukkit.getServer().removeBossBar(barNameKey);
                    notifications.getCooldownBar().removeAll();
                    hasBarShown.remove(player);
                }
                }
            }
            }
        }.runTaskTimer(Main.plugin, 0, 20);
        }
    }
     
    Here is the NotificationManager class I used for action bar messages and boss bars.
    Code (Text):
    package lucien.HardcoreGames.game;

    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.NamespacedKey;
    import org.bukkit.boss.BarColor;
    import org.bukkit.boss.BarFlag;
    import org.bukkit.boss.BarStyle;
    import org.bukkit.boss.BossBar;
    import org.bukkit.entity.Player;

    import com.connorlinfoot.actionbarapi.ActionBarAPI;

    public class NotificationManager {
        public static NamespacedKey gracePeriodBarNameKey = new NamespacedKey(Main.plugin, "gracePeriod");
        public static BossBar gracePeriodBar = Bukkit.getServer().createBossBar(gracePeriodBarNameKey, ChatColor.translateAlternateColorCodes('&', "&5&lGrace Period: &f10 minutes"), BarColor.WHITE, BarStyle.SEGMENTED_10, new BarFlag[0]);
        private BossBar cooldownBar;
     
        public static void showBossBar(BossBar barToShow, Player playerToShow) {
        barToShow.setVisible(true);
        barToShow.addPlayer(playerToShow);
        }
     
        public void createCooldownBar(NamespacedKey nameKey, String title, BarColor color, BarStyle style) {
        cooldownBar = Bukkit.getServer().createBossBar(nameKey, title, color, style, new BarFlag[0]);
        }
     
        public BossBar getCooldownBar() {
        return cooldownBar;
        }
    }
     
    Any help is appreciated, thanks in advance.

    EDIT: To clarify, the boss bar remains on the player's screen, and is not removed by
    Bukkit.getServer().removeBossBar(barNameKey);
    and
    notifications.getCooldownBar().removeAll();
    gives me a NullPointerException.
     
  2. md_5

    Administrator Developer

    NotificationManager notifications = new NotificationManager();

    You create a new NotificationManager each time, so cooldownBar will be null.

    You need to store it somewhere, perhaps in the map instead of an Integer and put the Integer as a field in NotificationManager
     
  3. Would I put the
    NotificationManager notifications = new NotificationManager();
    line as the first line of the startCooldownTimer() method? Or make a separate method that creates NotificationManagers? I'm new so i apologize if these questions are dumb.
     
  4. I think got it! Here's the finished code:

    Code (Text):
    package lucien.HardcoreGames.game;

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.UUID;
    import java.util.concurrent.ConcurrentHashMap;

    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.boss.BossBar;
    import org.bukkit.entity.Player;
    import org.bukkit.scheduler.BukkitRunnable;

    public class Cooldowns {
        public static ConcurrentHashMap<UUID, NotificationManager> cooldowns = new ConcurrentHashMap<UUID, NotificationManager>();
        public static HashMap<String, Integer> cooldownMasterList = new HashMap<String, Integer>();
        public static List<Player> hasBarShown = new ArrayList<Player>();

        public static void startCooldownTimer() {
        new BukkitRunnable() {
            @Override
            public void run() {
            if(!cooldowns.isEmpty()) {
                for(UUID uuid : cooldowns.keySet()) {
                Player player = Bukkit.getPlayer(uuid);
                NotificationManager notifications = cooldowns.get(uuid);
                int timeleft = notifications.getRemainingCooldown();
                BossBar cooldownBar = notifications.getCooldownBar();

                if(timeleft > 0) {
                    notifications.setRemainingCooldown(timeleft - 1);
                    int masterCooldown = cooldownMasterList.get(ChosenKits.playerKits.get(player.getName()));
                    if(masterCooldown != timeleft) {
                    if(cooldownBar.getProgress() - (1.0/masterCooldown) >= 0.0)
                        cooldownBar.setProgress(cooldownBar.getProgress() - (1.0/masterCooldown));
                    else
                        cooldownBar.setProgress(0.0);
                    cooldownBar.setTitle(ChatColor.translateAlternateColorCodes('&', "&8&lCooldown: &e" + timeleft));
                    }
                }
                else {
                    cooldowns.remove(uuid);
                    notifications.getCooldownBar().removePlayer(player);
                }
                }
            }
            }
        }.runTaskTimer(Main.plugin, 0, 20);
        }

        public static void fillMasterList() {
        cooldownMasterList.put("Thor", 10);
        }
    }
     
    and the NotificationManager:
    Code (Text):
    package lucien.HardcoreGames.game;

    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.NamespacedKey;
    import org.bukkit.boss.BarColor;
    import org.bukkit.boss.BarFlag;
    import org.bukkit.boss.BarStyle;
    import org.bukkit.boss.BossBar;
    import org.bukkit.entity.Player;

    import com.connorlinfoot.actionbarapi.ActionBarAPI;

    public class NotificationManager {
        public static NamespacedKey gracePeriodBarNameKey = new NamespacedKey(Main.plugin, "gracePeriod");
        public static BossBar gracePeriodBar = Bukkit.getServer().createBossBar(gracePeriodBarNameKey, ChatColor.translateAlternateColorCodes('&', "&5&lGrace Period: &f10 minutes"), BarColor.WHITE, BarStyle.SEGMENTED_10, new BarFlag[0]);
        private BossBar cooldownBar;
        private int cooldown;
       
        public NotificationManager(NamespacedKey nameKey, String title, BarColor color, BarStyle style, double progress, Player player, int cooldown) {
        cooldownBar = Bukkit.getServer().createBossBar(nameKey, title, color, style, new BarFlag[0]);
        cooldownBar.setProgress(1.0);
        cooldownBar.addPlayer(player);
        this.cooldown = cooldown;
        }
       
        public static void showBossBar(BossBar barToShow, Player playerToShow) {
        barToShow.setVisible(true);
        barToShow.addPlayer(playerToShow);
        }

        public static void playerInfoActionBar(Player attacker, Player victim) {
        if(!Tracking.cooldowns.containsKey(attacker.getUniqueId())) {
            String kitToDisplay = ChatColor.WHITE + "None";
            if(ChosenKits.playerKits.get(victim.getName()) != null)
            kitToDisplay = ChatColor.WHITE + ChosenKits.playerKits.get(victim.getName());
            ActionBarAPI.sendActionBar(attacker, ChatColor.translateAlternateColorCodes('&', "&5&lTarget: &f" + victim.getName() + " &5&lKit: &f" + kitToDisplay), 60);
        }
        }

        public BossBar getCooldownBar() {
        return cooldownBar;
        }
       
        public int getRemainingCooldown() {
        return cooldown;
        }
       
        public void setRemainingCooldown(int cooldown) {
        this.cooldown = cooldown;
        }
    }
     
    This makes it so that each player can have their own cooldown boss bar. Thank you so much for your suggestion, if there is anything else I could do to make this run better (less laggy) please let me know :)