Solved NullPointerExeption with runnable.

Discussion in 'Spigot Plugin Development' started by Exellanix, Jun 8, 2016.

  1. I am making a combat plugin that makes it so you can not kill steal. In doing so I get a null pointer on line 32 of my AntiKS class. I do not know what is wrong.

    Error:

    Code (Text):
    [23:53:45 INFO]: [AdvancedCombat] Enabling AdvancedCombat v0.3.0
    [23:53:45 ERROR]: Error occurred while enabling AdvancedCombat v0.3.0 (Is it up
    to date?)
    java.lang.NullPointerException
            at io.github.exellanix.advancedcombat.listeners.AntiKS.<init>(AntiKS.jav
    a:32) ~[?:?]
            at io.github.exellanix.advancedcombat.AdvancedCombat.registerEvents(Adva
    ncedCombat.java:76) ~[?:?]
            at io.github.exellanix.advancedcombat.AdvancedCombat.onEnable(AdvancedCo
    mbat.java:54) ~[?:?]
            at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:321) ~[s
    pigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader
    .java:340) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManage
    r.java:405) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugin(CraftServer.jav
    a:357) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at org.bukkit.craftbukkit.v1_8_R3.CraftServer.enablePlugins(CraftServer.
    java:317) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at net.minecraft.server.v1_8_R3.MinecraftServer.s(MinecraftServer.java:4
    14) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at net.minecraft.server.v1_8_R3.MinecraftServer.k(MinecraftServer.java:3
    78) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at net.minecraft.server.v1_8_R3.MinecraftServer.a(MinecraftServer.java:3
    33) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at net.minecraft.server.v1_8_R3.DedicatedServer.init(DedicatedServer.jav
    a:263) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java
    :524) [spigot-1.8.8.jar:git-Spigot-fdc1440-53fac9f]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_66]
     
    AntiKS:

    Code (Text):
    package io.github.exellanix.advancedcombat.listeners;

    import io.github.exellanix.advancedcombat.AdvancedCombat;
    import io.github.exellanix.advancedcombat.util.DamageTracker;
    import me.exellanix.kitpvp.event.custom.PlayerBowKillEvent;
    import me.exellanix.kitpvp.event.custom.ThorAxeKillEvent;
    import net.milkbowl.vault.economy.EconomyResponse;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.entity.EntityDamageByEntityEvent;
    import org.bukkit.event.entity.PlayerDeathEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerKickEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.scheduler.BukkitRunnable;

    import java.util.HashMap;

    /**
    * Created by Exellanix on 5/15/2016.
    */

    public class AntiKS implements Listener {

        private HashMap<Player, DamageTracker> damage = new HashMap<>();

        public AntiKS() {
            AdvancedCombat.getSingleton().getServer().getScheduler().runTaskTimer(AdvancedCombat.getSingleton(), () -> {
                for(Player p : Bukkit.getOnlinePlayers()) {
                    damage.get(p).decrementCooldown();
                }
            }, 0, 20);
        }

        @EventHandler(priority = EventPriority.MONITOR)
        public void onDamage(EntityDamageByEntityEvent event) {
            if(event.getDamager() instanceof Player && event.getEntity() instanceof Player) {
                if(event.getEntity() != event.getDamager()) {
                    if(!event.isCancelled()) {
                        damage.get(event.getEntity()).takeDamage((Player) event.getDamager(), event.getFinalDamage());
                    }
                }
            }
        }

        @EventHandler(priority = EventPriority.MONITOR)
        public void onThor(ThorAxeKillEvent event) {
            Player damage = event.getVictim();
            Player damager = event.getUser();

            if(damage != damager) {
                if(!event.isCancelled()) {
                    this.damage.get(damage).takeDamage(damager, event.getDamage());
                }
            }
        }

        @EventHandler(priority = EventPriority.MONITOR)
        public void onShot(PlayerBowKillEvent event) {
            Player damage = event.getVictim();
            Player damager = event.getShooter();
             if(damage != damager) {
                 if(!event.isCancelled()) {
                     this.damage.get(damage).takeDamage(damager, event.getDamage());
                 }
             }
        }

        @EventHandler
        public void onJoin(PlayerJoinEvent event) {
            damage.put(event.getPlayer(), new DamageTracker());
        }

        @EventHandler
        public void onQuit(PlayerQuitEvent event) {
            damage.remove(event.getPlayer());
        }

        @EventHandler
        public void onKick(PlayerKickEvent event) {
            damage.remove(event.getPlayer());
        }

        @EventHandler
        public void onDeath(PlayerDeathEvent event) {
            if(damage.get(event.getEntity()).getCooldown() > 0) {
                Player killer = damage.get(event.getEntity()).getKiller();
                if(killer != null) {
                    Player player = event.getEntity();
                    EconomyResponse r = AdvancedCombat.getSingleton().getEcon().depositPlayer(killer, 1.00);
                    if (r.transactionSuccess()) {
                        killer.sendMessage(ChatColor.GREEN + "You have recieved $1 for killing" +  player.getDisplayName());
                    }

                    player.sendMessage(ChatColor.RED + "You have been killed by " + killer.getDisplayName() + "!");

                    //TODO make death messages in another death event

                }
            }
            damage.get(event.getEntity()).resetCooldown();
        }

        public HashMap<Player, DamageTracker> getDamage() {
            return damage;
        }
    }
     
    Main class:

    Code (Text):
    package io.github.exellanix.advancedcombat;

    import io.github.exellanix.advancedcombat.commands.AdvancedCombat_Command;
    import io.github.exellanix.advancedcombat.listeners.AntiKS;
    import io.github.exellanix.advancedcombat.listeners.CombatTagEventCaller;
    import io.github.exellanix.advancedcombat.listeners.Tag;
    import net.milkbowl.vault.economy.Economy;
    import org.bukkit.Bukkit;
    import org.bukkit.ChatColor;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.PluginDescriptionFile;
    import org.bukkit.plugin.PluginManager;
    import org.bukkit.plugin.RegisteredServiceProvider;
    import org.bukkit.plugin.java.JavaPlugin;
    import org.bukkit.scheduler.BukkitRunnable;

    import java.util.ArrayList;
    import java.util.UUID;
    import java.util.logging.Logger;

    /**
    * Created by Exellanix on 5/8/2016.
    */
    public class AdvancedCombat extends JavaPlugin {

        private static AdvancedCombat singleton;

        private AntiKS antiks;

        public String getPrefix = ChatColor.GOLD + "" + ChatColor.BOLD + "CombatTag " + ChatColor.DARK_GRAY + "⇨ ";

        private Economy econ = null;

        private boolean setupEconomy() {
            RegisteredServiceProvider<Economy> economyProvider;
            economyProvider = getServer().getServicesManager()
                    .getRegistration(Economy.class);
            if (economyProvider != null) {
                econ = economyProvider.getProvider();
            }

            return (econ != null);
        }

        public void onEnable() {
            if (!setupEconomy()) {
                getLogger().warning("Could not setup the economy!");
                getLogger().warning("Make sure you have an economy plugin installed!");
                getServer().getPluginManager().disablePlugin(this);
            }else {
                PluginDescriptionFile pdfFile = getDescription();
                Logger logger = Logger.getLogger("Minecraft");

                registerEvents();
                registerCommands();
                singleton = this;

                logger.info(pdfFile.getName() + " has been enabled! (V." + pdfFile.getVersion());
            }
        }

        public void onDisable() {
            PluginDescriptionFile pdfFile = getDescription();
            Logger logger = Logger.getLogger("Minecraft");


            logger.info(pdfFile.getName() + " has been disabled! (V." + pdfFile.getVersion());

        }

        public void registerCommands() {
            getCommand("advancedcombat").setExecutor(new AdvancedCombat_Command());
        }

        public void registerEvents() {
            antiks = new AntiKS();
            PluginManager pm = getServer().getPluginManager();

            pm.registerEvents(new CombatTagEventCaller(), this);
            pm.registerEvents(antiks, this);
            pm.registerEvents(new Tag(), this);
        }

        public Economy getEcon() {
            return econ;
        }

        public static AdvancedCombat getSingleton() {
            return singleton;
        }

        public AntiKS getAntiKS() {
            return antiks;
        }

        public ArrayList<Player> inCombat = new ArrayList<Player>();
    }
     
     
  2. There needs to be a stickied thread that says, "If you have an error, show the gawd damn line that the error is one" :mad:

    Anyway, which line is the error?
     
  3. Remove the "singleton", switch to constructor dependency injection (fancy term for passing objects to other objects using their constructor), and magically watch your problems go away.

    Also, use abstract classes/interfaces over concrete classes when it comes to field types (I.e. Map vs HashMap) - a rule of thumb is to pick the least specific type you need. Moreover, it's not necessary to both listen to kick and quit for cleanup :p.
     
    • Like Like x 1
  4. I said that the line was 32 in my AntiKS class


    So do you mean something like:

    Code (Text):
    private SomeClass someClass;

    public AntiKS(SomeClass someClass) {

    this.someClass = someClass;

    }
    ?
     
  5. Yes, exactly that. Rather than depending on your 'getSingleton' method, pass it to the constructor. That way, regardless of in what order you initialise things, the instances will always be available.
     
  6. Hmm, I just did that and I still get the error.
     
  7. Post updated code? Did you swap the old getSingleton usage with the plugin parameter passed through the constructor?
     
  8. in your initial code, just move the line
    singleton = this;
    2 lines up so that its before you try to register your events
     
  9. Thank you so much, I did not catch that.

    I did, and thank you for recommending that method.
     
  10. Off-topic, but i am curious, what is the benefit of doing this? Is it simply convention aimed at making code more compatible with different kinds of collections (ex: a method that takes List instead of LinkedList or ArrayList)?
     
  11. That's a big part of it, yes. I've also heard that (iirc) ConcurrentHashMap broke when people went from Java 7 to Java 8 when they used ConcurrentHashMap as a type instead of Map.

    It's also part of SOLID, namely Liskov Substitution Principal .