NullPointerException w/ HashMap

Discussion in 'Plugin Development' started by Wheaties66613, Mar 13, 2021.

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

    Wheaties66613

    Hey everyone,
    I'm trying to code a cooldown system for a plugin, and I'm running into problems.
    Context: Trident spawns drowned whenever you throw it, I'm trying to make a 30 second cooldown between entity spawning.
    This is the relevant section of my events class. It's messy because troubleshooting sucks:
    Code:
    @EventHandler
        public void onTridentLand(ProjectileHitEvent e) {
            if (!e.getEntityType().equals(EntityType.TRIDENT)) {return;}
            if (!(e.getEntity().getShooter() instanceof Player)) {return;}
            Player p = (Player) e.getEntity().getShooter();
            UUID pID = p.getUniqueId();
            Cooldown c = new Cooldown(plugin);
            Cooldown.setupMap();
            if(TRIDENT.contains(pID)) {
                if(Cooldown.cooldown.containsKey(pID)) {
                    p.sendMessage(ChatColor.RED + "You are still on cooldown. "
                            + "You have " + Cooldown.getCooldown(p.getUniqueId()) + " seconds left.");
                    return;
                } else {
                    for(int i = 0; i < 3; i++) {
                        e.getEntity().getLocation().setX(e.getEntity().getLocation().getX() + 1);
                        p.getWorld().spawnEntity(e.getEntity().getLocation(), EntityType.DROWNED);
                    }
                    Cooldown.setCooldown(pID, 30);
                    c.startCooldown(pID);
                    p.sendMessage("You are now in cooldown");
                }
            }
        }
    Here is my cooldowns class. I'll slap the whole thing in here, all of it is used anyway:
    Code:
    package io.github.wheaties66613;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    import org.bukkit.Bukkit;
    
    public class Cooldown {
        private final Core plugin;
        public Cooldown(Core plugin) {
            this.plugin=plugin;
        }
       
        public static Map<UUID, Integer> cooldown;
       
        public static void setupMap() {
            cooldown = new HashMap<UUID, Integer>();
        }
       
        public static int getCooldown(UUID pID) {
            return cooldown.get(pID);
        }
       
        public static void setCooldown(UUID pID, int time) {
            cooldown.put(pID, time);
        }
       
        public void startCooldown(final UUID pID) {
            Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
    
                @Override
                public void run() {
                    int time = cooldown.get(pID);
                    if(time != 0) {
                        cooldown.put(pID, time - 1);
                    } else {
                        cooldown.remove(pID);
                        Bukkit.getScheduler().cancelTasks(plugin);
                    }
                   
                }
               
            }, 0L, 20L);
        }
    }
    
    I'm not getting any errors in the log, the cooldown just won't enact. Every time I throw the trident, the drowned spawn and the "you're now in cooldown" message plays. My working theory is that the player's ID is not being entered properly into the hashmap, but that sounds dumb as I'm typing it out. Any advice is appreciated. Sorry if this is a beginner's mistake.

    P.S. I have tried the System.CurrentTimeInMills() approach, but it's never worked for me. Trying a different approach. :)
     
    Last edited: Mar 13, 2021
  2. Offline

    Strahan

    You're creating a new instance of Cooldown every time it hits, so of course it will never remember. You need the instances to persist.

    That said, I don't see why you are screwing with a custom object and runnables for this in the first place. You're making it way more complicated than it needs to be. Just make a Map<UUID, Long> and store the expiration time then when the cooldown would need to be checked, see if the stored time is greater than current time.

    PS - You don't need curly brackets when they are enclosing only one command, you should follow naming conventions - all caps should only be used for constants and when you are doing a return within a logic block, there is no need for "else". You can drop that and reduce unnecessary indentation.
     
    Last edited: Mar 14, 2021
Thread Status:
Not open for further replies.

Share This Page