Solved BukkitScheduler Trouble :/

Discussion in 'Plugin Development' started by Dippoakabob, Mar 18, 2013.

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

    Dippoakabob

    I am working on re-vamping a timer/counting system for my server that I've been working on, but I just can't seem to get this new method of counting down. I've used the BukkitScheduler before, but it's not working with my current setup. Any help/advice would be much appreciated.

    This is the current 'Timer' class (or at least the issue part).
    This is the constructor method that is called by another class.
    Code:
    public class Timer{
       
        private int timer;
        private int time;
        private int startTime;
        private MGroup group;
        private Long interval;
        Main plugin;
       
        public Timer(Long interval, Main instance, MGroup currentGroup){
            group = currentGroup;
            this.interval = interval;
            plugin = instance;
            time = 0;
     
    /* 21 (issue line) */  timer = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
                public void run(){
                    if(time>0){
                        time--;
                        if(time % 30 == 0){
                            for(Player n : group.getPlayers()){
                                group.messagePlayer(n, "&7| Current Map: &a" + group.getMap() +
                                        "\n&7| Time Remaining: &a" + group.getFormattedTime());
                            }
                        } else if(time <= 10){
                            if (time < 5 && time > 0 || time % 5 == 0){
                                for(Player n : group.getPlayers()){
                                    group.messagePlayer(n, "&a| New map in " + time + " seconds.");
                                }
                            }
                        }
     
                    }else if(time==0){
                        time--;
                        group.changeMaps();
                    }
                }
            }, 0L, this.interval);
        }
    When called, the "time" value is set, but the counter doesn't count down.
    The log says that there is a NULLPointerException at the place where the counter is initialized. If anyone could help, please do :)

    Show Spoiler

    This is the old method, it worked, but I didn't like how it was not a BukkitScheduler task.
    Code:
    public class Timer implements Runnable {
            MGroup group;
            int time;
     
            public Timer(int time, MGroup mGroup){
                this.time = time*60 + 1;
                group = mGroup;
            }
     
     
     
            public void setTime(int timeMinute){
                time = (timeMinute*60);
            }
     
            public int getTime(){
                return time;
            }
     
     
            public void run() {
                try{
                    while(time > 0 && running){
                        Thread.sleep(1000);
                        time--;
                        group.time = time;
                        if(time % 30 == 0){
                            for(Player n : group.getPlayers()){
                                group.messagePlayer(n, "&7| Current Map: &a" + group.getMap() +
                                        "\n&7| Time Remaining: &a" + group.getFormattedTime());
                            }
                        } else if(time <= 10){
                            if(time %5 ==0){
                                for(Player n : group.getPlayers()){
                                    group.messagePlayer(n, "&a| New map in " + time + " seconds.");
                                }
                            }else if (time < 5 && time > 0){
                                for(Player n : group.getPlayers()){
                                    group.messagePlayer(n, "&a| New map in " + time + " seconds.");
                                }
                            }
                        }
                        if(!running) this.time = 0;
                    }
                    if(!running)return;
                    group.changeMaps();
                }catch(Exception ig){
     
                }
            }
        }

    Here's the stack trace:
    Show Spoiler

    Code:
    2013-03-21 19:13:52 [SEVERE] Could not load 'plugins\MelonJump.jar' in folder 'plugins'
    org.bukkit.plugin.InvalidPluginException: java.lang.NullPointerException
        at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:182)
        at org.bukkit.plugin.SimplePluginManager.loadPlugin(SimplePluginManager.java:305)
        at org.bukkit.plugin.SimplePluginManager.loadPlugins(SimplePluginManager.java:230)
        at org.bukkit.craftbukkit.v1_5_R1.CraftServer.loadPlugins(CraftServer.java:239)
        at org.bukkit.craftbukkit.v1_5_R1.CraftServer.reload(CraftServer.java:594)
        at org.bukkit.Bukkit.reload(Bukkit.java:184)
        at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:23)
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:186)
        at org.bukkit.craftbukkit.v1_5_R1.CraftServer.dispatchCommand(CraftServer.java:514)
        at org.bukkit.craftbukkit.v1_5_R1.CraftServer.dispatchServerCommand(CraftServer.java:506)
        at net.minecraft.server.v1_5_R1.DedicatedServer.am(DedicatedServer.java:261)
        at net.minecraft.server.v1_5_R1.DedicatedServer.r(DedicatedServer.java:226)
        at net.minecraft.server.v1_5_R1.MinecraftServer.q(MinecraftServer.java:476)
        at net.minecraft.server.v1_5_R1.MinecraftServer.run(MinecraftServer.java:409)
        at net.minecraft.server.v1_5_R1.ThreadServerApplication.run(SourceFile:573)
    Caused by: java.lang.NullPointerException
        at net.streamwhistle.MelonJump.Timer.<init>(Timer.java:21)
        at net.streamwhistle.MelonJump.MGroup.<init>(MGroup.java:31)
        at net.streamwhistle.MelonJump.Main.<init>(Main.java:32)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:178)
        ... 14 more

    If you need more info just ask.
     
  2. Offline

    Nitnelave

    Never do a try ... catch (Exception e), you never know what error you're getting. You should have a valid reason to catch every exception, and detail them and handle them. Here you're asking for a NPE without knowing it...

    What I would do would be when you call start, it schedules a repeating (async ?) task every 30 s that tells players how much time is left, and another one that will start 10 s before the end. The second one will tell people how much time is left, and create a repeating task telling it at the end, etc....

    That's one way of doing it.

    Another way, closer to what you had in mind, would be to have your Timer implement Runnable, and in the start or initiate method (it can't be the run() method, because that is reserved by the Runnable interface) you do a Bukkit.getScheduler().scheduleSyncTask(plugin, this, 20, 20). And in the run() method, you can decrease the time counter, and send your messages apropriately.
     
  3. plugin == null
    most found error
     
  4. Offline

    Dippoakabob

    the 'plugin' was defined in the constructor and calls my main class. I've programmed plugins before, I know not to set my plugin to null.

    I'll try it, but I'm a bit confused on the first part of your reply; I wasn't using a try/catch statement.

    to have the time count down, should it just go down by thirties? or have another counter?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
  5. Offline

    Nitnelave

    Well, the question is : Do you only need the counter for what is present in the message (sending messages to players), or do you need to have access to the current time of the counter? Because that changes everything.
    Basically, you can do either method : you calculate when each of the messages will be sent and your create a task for each of them (grouping them when appropriate); or you create a countdown task that runs every second, and you check every second if you should send a message.
    If you don't need to access the current time, the first solution might be the best, and if you do, the second one is the simplest (although you can also use the first one and calculate the time left from the starting time and the total time).
     
  6. Offline

    Dippoakabob

    I need to be able to access the current time and send it to the player when they join a certain arena. Another issue that I have 2 Arenas that need to be running, separately. I've been having trouble with the counter, so any more advice would be nice.
     
  7. Offline

    Nitnelave

    Well, I told you both possibilities : either calculate in advance what has to be displayed when, and run tasks accordingly (one task every 30s to say how much time is left, one task for the end of the counter). Or run a task every second to count down the timer.
     
  8. Offline

    dillyg10

    Pro tip: Sync thread is very unpredictable, 1 second can equal 5 seconds, even if you don't see the server visually lagging.

    Also, why are you using a timer... the easiest thing to do is to just use the current mills of the system.
     
  9. Offline

    Dippoakabob

    I'll try it out, I haven't used the milliseconds with bukkit before, can you give a short example?
     
  10. Offline

    Nitnelave

    It's not a Bukkit feature, but a Java one. Just System.timeInMillis () or something like that will return a long with the time in milliseconds... but I guess you would still need to run a recurrent task to check how much time has elapsed.
     
  11. Offline

    Dippoakabob

    Okay, I have the method of how to get the counter working, but what do I do about the NPE, It won't go away no matter what I try. I think it may have something to do with a counter in a class that there are multiple objects in. PLEASE help. This is starting to get a bit frustrating.

    According to the stack trace, the issue is right where the timer is defined. I really want to get this done soon, so if you have any input please tell me

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
  12. Offline

    AmShaegar

    Could you post the whole stack trace?
     
  13. Offline

    Dippoakabob

    Yeah, I've made a few changes to the code, so let me just update above and I'll add a spoiler of the stack trace

    Updated

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
  14. Offline

    AmShaegar

    Ah, took some time to figure out what you did but I bet that you are trying to start the Timer from you Main's constructor public Main() {...}.

    Do not do that. Use onEnable for that. Some of the Bukkit helpers are not yet ready to use in this state.
     
  15. Offline

    Dippoakabob

    Actually it is called from the MGroup object's changeMap() method. That method is called from the constructor, but not until after it runs through some other things. Is there still an issue with that?

    There are multiple instances of that MGroup object tho. So could there be an issue there?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 31, 2016
  16. Offline

    AmShaegar

    jup. you must wait for the main constructor to be fully loaded. best practice is to ignore it completely or at least do not use it to do bukkit related stuff.
     
  17. Offline

    Dippoakabob

    I'll try calling it in the onEnable() method and then I'll be back.
     
  18. Offline

    AmShaegar

    getting some sleep now. hope that solved your problem. will check back tomorrow.
     
  19. Offline

    Dippoakabob

    Same error :/
     
  20. Offline

    Nitnelave

    A good way to debug would be to add checks for plugin == null, group == null, plugin.getServer() == null, etc... and display a message in case of null, just before line 21.
     
  21. Offline

    Dippoakabob

    Got it! thanks @Nitnelave and @AmShaegar it works now. There was an issue with where the Timer class was being called, only it was where inside of the MGroup class, not just Main. Thanks so much!
     
Thread Status:
Not open for further replies.

Share This Page