Solved make a loop with waiting time

Discussion in 'Plugin Development' started by HenkDeKipGaming, Jun 30, 2015.

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

    HenkDeKipGaming

    hey, i have a really simple question here :D
    how do i make a loop so it'll keep doing the piece of code in the loop, but it doesn't spam it, it does it once every 40 ticks or something. can someone tell me how to do this? or show me an example? thanks! :D
    you guys are the best :D
     
  2. Offline

    nj2miami

  3. Offline

    HenkDeKipGaming

    It gives an error on pluginInstance

    EDIT: i actually want to use this for a scoreboard... so this is in a playerjoinevent. i don't know if that changes anything?
     
  4. Offline

    CrystallFTW

    @HenkDeKipGaming If you are using this in a main class, remove pluginInstance and type "this" if not, in your main class add
    Code:
        public static JavaPlugin instance;
    and in onEnable() add
    Code:
    instance = this;
    then in the scheduler, instead of adding "this" add "Mainclass.instance" .
     
  5. @HenkDeKipGaming

    It doesn't change anything.
    Are you in your main class? If so, define a variable called "instance" and place it at the top of the class(right below public class).

    Code:
    public static MainClassName instance;
    Replace MainClassName with class name. This class and code should be in the class that extends JavaPlugin. Now in the onEnable(), add this:

    Code:
    instance = this;
    This should be the first thing in the onEnable(). Now change "pluginInstance" to "instance".

    If your listener is in another class, make sure to add this into the top of your other class:

    Code:
    private static MainClassName instance = MainClassName.instance;
    Edit: Ninja'd by @CrystallFTW
     
  6. Offline

    CrystallFTW

  7. Offline

    Ruptur

    @HenkDeKipGaming
    Thats because you dont copy word for word. The pluginInstance (pretty self explanatory) is the instance of your main class. Also people dont just post links of it is had no irrelevance to the topic.

    You will need to run a thread (bukkitrunnable) to run something every x amount of ticks
    An example for one using the scheduler
    Code:
    getScheduler().scheduleRepeatingTask(instance, new Runnable() {
        @Override
         public void run() {
             // code to run
        }
    }, delay, interval);
    delay -(long) is the amont to ticks to wait before running
    interval -  (long) is the amont of ticks between each run. 
    
     
  8. Offline

    HenkDeKipGaming

    okey, so i got this:
    Code:
    @EventHandler
            public void onJoin(final PlayerJoinEvent e){
    Bukkit.getServer().getScheduler().runTaskTimer(this, new Runnable() {
                   public void run() {
                      ScoreboardManager manager = Bukkit.getScoreboardManager();
                      
                         Scoreboard scoreboard = manager.getNewScoreboard();
                    
                         Objective obj = scoreboard.registerNewObjective("Board", "dummy");
                         obj.setDisplaySlot(DisplaySlot.SIDEBAR);
                         obj.setDisplayName("Kingdom points:");
                        
                         Score vystara = obj.getScore("Vystara: ");
                         vystara.setScore(getConfig().getInt("groups.kingdom.vystaraPoints"));
                         e.getPlayer().setScoreboard(scoreboard);
                         Score vidal = obj.getScore("Vidal: ");
                         vidal.setScore(getConfig().getInt("groups.kingdom.vidalPoints"));
                         e.getPlayer().setScoreboard(scoreboard);
                         Score lorien = obj.getScore("Lorien: ");
                         lorien.setScore(getConfig().getInt("groups.kingdom.lorienPoints"));
                         e.getPlayer().setScoreboard(scoreboard);
                         Score utopia = obj.getScore("Utopia: ");
                         utopia.setScore(getConfig().getInt("groups.kingdom.utopiaPoints"));
                         e.getPlayer().setScoreboard(scoreboard);
                         Score tribal = obj.getScore("Tribal: ");
                         tribal.setScore(getConfig().getInt("groups.kingdom.tribalPoints"));
                         e.getPlayer().setScoreboard(scoreboard);
                         Score warday = obj.getScore("§6" + ChatColor.MAGIC + "K" + ChatColor.RED + ChatColor.BOLD + " HET IS WARDAY " + "§6" +  ChatColor.MAGIC + "K");
                         if(getConfig().getString("saturday").equalsIgnoreCase("yes")){
                         warday.setScore(-100);
                         e.getPlayer().setScoreboard(scoreboard);
                         }
                   }
                }, 40L, 40L);
              
            }
    
    it still doesn't update... why?

    EDIT: it does! sorry :)
    thanks for your help guys!

    SOLVED
     
    Last edited: Jun 30, 2015
  9. Do not do this, at all. If a player leaves, this task will continue to run, using player methods even though the player doesn't exist. You need to store the task ID in a Map along with the player's UUID, and then in PlayerQuitEvent, if the Map contains their UUID, remove their UUID and cancel the task. Also, in onEnable(), you might want to loop through every player online and start the task, as when the plugin is disabled (reloaded), the scheduled tasks may be cancelled thus need to be restarted again.

    E.g.
    Code:
    private Map<UUID, Integer> scoreboardTasks = new HashMap<>();
    
    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        final Player player = event.getPlayer();
        this.scoreboardTasks.put(player.getUniqueId(), player.getServer().getScheduler().runTaskTimer(this, new Runnable() {
            public void run() {
                // Additionally, you can do: if (!player.isOnline()) return;
                player.sendMessage("Hi!");
            }
        }, 40L, 40L).getTaskId());
    }
    
    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
       if (this.scoreboardTasks.containsKey(event.getPlayer().getUniqueId())) event.getPlayer().getScheduler().cancelTask(this.scoreboardTasks.remove(event.getPlayer().getUniqueId()));
    }
    
    Please don't give code/suggest using static instances of a plugin. Not going to explain why as I use static instances myself, but it's bad.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 12, 2016
  10. The way I use statics in my example is perfectly okay. Statics aren't a bad thing if they're being used in certain ways. We use them all the time in java(though we don't have to) and that's okay.
     
  11. No sir, you are incorrect. This way is the way I was talking about, not to have a static instance of your plugin. I'm not very experienced with statics in Java, so I cannot explain why.

    I'm not sure if someone like @mythbusterma or @AdamQpzm has any explanations?
     
  12. I've used them for years without any noticeable problems. But if @mythbusterma or @AdamQpzm would care to explain that would be great.
     
  13. Offline

    nj2miami

    @HeyAwesomePeople @KingFaris11 @HenkDeKipGaming

    Because anything that references the static reference will not unload properly or be disposed of during garbage collections which will eventually create memory leaks. Static references to the main plugin is poor at best and dangerous at its worst.

    Simply PASS the reference as needed.

    private MainClass main;

    onEnable() {
    main = this;

    Then:
    someClass(main);

    In that 'someClass' constructor, simply expect the reference.

    Code:
    public class someClass {
      private MainClass main;
      public someClass(MainClass m) {
        main = m;
    }
    99% of all plugins being written asking for help on these forums should not be using static references to its main class. Example where static is appropriate for a class would be a utility class, but not to STORE a static reference to a class.

    For instance:

    Code:
    public class ConvertTime {
      public static String doIt(Long time) {
        // do some string manipulation to return a formatted string
        return SomeString;
      }
    }
    Then from any class simply call SomeString = ConvertTime.doIt(SomeLong);
     
Thread Status:
Not open for further replies.

Share This Page