Solved ASync Tasks

Discussion in 'Plugin Development' started by cfil360, May 8, 2015.

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

    cfil360

    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);
        }
     
    Last edited: May 8, 2015
  2. Offline

    Tecno_Wizard

    @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?
     
  3. Offline

    cfil360

    @Tecno_Wizard i have updated the code. That class is the only thing that modifies an arena before the countdown.
     
  4. Offline

    Tecno_Wizard

    @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.
     
    Last edited: May 8, 2015
  5. Offline

    cfil360

    @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;
            }
     
  6. Offline

    mythbusterma

    @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.
     
  7. Offline

    cfil360

    @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.
     
  8. Offline

    mythbusterma

    @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.
     
  9. Offline

    Tecno_Wizard

    @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.
     
  10. Offline

    cfil360

    @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.
     
Thread Status:
Not open for further replies.

Share This Page