I am trying to do some stuff within an async task. However when i try to call an event, the task errors and it tells me there is a null pointer exception. it doesn't give me any sort of line number or anything. As you can see i output the 2 variables being passed to the event, and they both output correctly. I am unsure as to what is null. Error Code: Task #21 for GC v1.0 generated an exception java.lang.NullPointerException Code Code: public class Countdown extends BukkitRunnable { private Arena arena; private int i; private ArrayList<Integer> countingNums; public Countdown(Arena arena, int start, int... cNums) { this.arena = arena; this.i = start; this.countingNums = new ArrayList<Integer>(); for (int c : cNums) { countingNums.add(c); } } @Override public void run() { if (i == 0) { arena.sound(Sound.WITHER_DEATH); arena.message(ExxtraPlayer.MsgType.INFO, "The game has begun!"); GameCore.getPlugin().getServer().getScheduler().scheduleSyncDelayedTask(GameCore.getPlugin(), new Runnable() { @Override public void run() { Bukkit.broadcastMessage(arena.getName()); Bukkit.broadcastMessage(arena.getGame().getName()); //new game start event1 Bukkit.getServer().getPluginManager().callEvent(new GameStartEvent(arena.getGame(), arena)); } }, 0L); cancel(); return; } if (countingNums.contains(i)) { arena.sound(Sound.NOTE_PLING); arena.message(ExxtraPlayer.MsgType.INFO, "The game will begin in " + i + " seconds."); } i--; } } Code before the countdown Code: public void start() { //set the arena game state to started arena.setState(GameState.STARTED); //heal all players for(ExxtraPlayer player : arena.getPlayers()) { player.getPlayer().setHealth(player.getPlayer().getMaxHealth()); } //feed all players for(ExxtraPlayer player : arena.getPlayers()) { player.getPlayer().setFoodLevel(20); } //teleport the players to the spawns for(int x = 0; x < arena.getPlayers().size() - 1; x++) { arena.getPlayers().get(x).getPlayer().teleport(arena.getMap().getSpawns().get(x)); } //freeze all the players for(ExxtraPlayer player : arena.getPlayers()) { player.freeze(); } //notify them of the map being played arena.message(ExxtraPlayer.MsgType.INFO, "The game will be played on " + arena.getMap().getName()); //begin a countdown new Countdown(arena, 3, 30, 20, 15, 10, 5, 4, 3, 2, 1).runTaskTimerAsynchronously(HungerGames.getPlugin(), 0, 20); }
@cfil360, sysout\sout til you drop. Put a print out line after everything that you think could cause this with a unique string. See which is the last to run. I have a feeling that you have a thread safety issue with the arena object. What do you do to its alias while this is waiting to run?
@Tecno_Wizard i have updated the code. That class is the only thing that modifies an arena before the countdown.
@cfil360, the first thing that stands out to me is that this is going to lagg once it works, a lot. All of these operations can be done with one iterator. Second, it's still your code. Add in the sout calls so you know what line the error is in and report back here if you still cannot find the cause with the line that is trowing the error. I can't do much with the info you have given me. It needs to be run, and I can't do that.
@Tecno_Wizard So i null checked for all variables of arena, and none of them are null. i also placed all the code within the countdown inside a try and catch, but i didn't receive the proper stack trace. All i received was Code: [Warn] java.lang.NullPointerException Code: public void run() { if (i == 0) { arena.sound(Sound.WITHER_DEATH); arena.message(ExxtraPlayer.MsgType.INFO, "The game has begun!"); GameCore.getPlugin().getServer().getScheduler().scheduleSyncDelayedTask(GameCore.getPlugin(), new Runnable() { @Override public void run() { try { Bukkit.broadcastMessage(String.valueOf(arena.getGame() == null)); Bukkit.broadcastMessage(String.valueOf(arena.getId() == 0)); Bukkit.broadcastMessage(String.valueOf(arena.getName() == null)); Bukkit.broadcastMessage(String.valueOf(arena.getLobby() == null)); Bukkit.broadcastMessage(String.valueOf(arena.getMap() == null)); Bukkit.broadcastMessage(String.valueOf(arena.getSelection() == null)); Bukkit.broadcastMessage(String.valueOf(arena.getStartGameExecutor() == null)); Bukkit.broadcastMessage(String.valueOf(arena.getEndGameExecutor() == null)); Bukkit.broadcastMessage(String.valueOf(arena.getState() == null)); Bukkit.broadcastMessage(String.valueOf(arena.getPlayers() == null)); //new game start event1 Bukkit.getServer().getPluginManager().callEvent(new GameStartEvent(arena.getGame(), arena)); } catch (Exception e) { e.printStackTrace(); } } }, 0L); cancel(); return; }
@cfil360 First off, just run it synchronously. There's no reason to do it asynchronously. Second, you didn't post the entire stack trace, which would tell you exactly where the error is.
@mythbusterma 1st it's better practice to run countdowns outside of the main thread. And 2nd. That is the entire stack trace. That is why I am unable to solve the problem. There is no other text saying where the line occurred and in what class like normal. Idk what is causing this.
@cfil360 No, it's not "better practice," it's completely irrelevant what thread it's run on (other than the for the thread-safety of the server, which you have failed to respect). I assume you're using Spigot, enable the "debug mode" or whatever they call it.
@cfil360, I think I found your problem. The async javadocs CLEARLY says to not use any static references to bukkit in an async. Thread safety issues galore because none of bukkit's methods are synchronized to avoid deadlock. I think your error is because of that. Bukkit itself is throwing the error, and that's why the stack trace is cut off, bukkit is handling it itself.
@Tecno_Wizard @mythbusterma Found the error. I had forgotten to return the handlers in the GameStartEvent. I was just returning null. Thanks for all your help.