Problem with Scheduler and players

Discussion in 'Plugin Development' started by Brut, Aug 8, 2014.

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

    Brut

    I'm developing a plugin that involves teleporting all players between their home and work locations at set times, with a 1 second delay between teleporting each player. I'm having a bit of trouble passing a single player object from an array into a .runTaskLater scheduler.

    I've been using the console logger to try and diagnose the issue, I'm confident that everything in the ShiftScheduler is OK as when the for loop is executed, <player 1> and <player 2> are displayed on the console.

    The issue appears to be with the ShiftHandler. Using the console logger, the two instances of ShiftHandler (one instance per player on the server) appear to execute at the correct time (one second apart) but <player 2> is displayed on the console twice instead of <player 1> and <player 2>

    The effect this has in game is that the last player to join the server is teleported correctly but everyone else is ignored.

    ShiftScheduler:
    Code:java
    1. public class ShiftScheduler extends BukkitRunnable {
    2.  
    3. private final JavaPlugin plugin;
    4. public final Logger logger = Logger.getLogger("Minecraft");
    5.  
    6. public static Player[] onlinePlayers;
    7. public static MySQL mySQL;
    8.  
    9. public static String nextShift = "";
    10. public static BukkitTask shiftHandler[];
    11.  
    12. public ShiftScheduler(JavaPlugin plugin, String nextShift) {
    13. this.plugin = plugin;
    14. this.nextShift = nextShift;
    15. }
    16.  
    17. @SuppressWarnings("deprecation")
    18. @Override
    19. public void run() {
    20. mySQL = new MySQL();
    21.  
    22. int noOfPlayers = 0;
    23. String playerShift = "";
    24. String uuid = "";
    25. onlinePlayers = Bukkit.getOnlinePlayers();
    26. noOfPlayers = onlinePlayers.length;
    27. shiftHandler = new BukkitTask[noOfPlayers+1];
    28.  
    29. for(int i=0; i<noOfPlayers; i++){
    30. playerShift = mySQL.getShift(onlinePlayers[i].getUniqueId().toString());
    31. uuid = onlinePlayers[i].getUniqueId().toString();
    32.  
    33. //tp player to work
    34. if(mySQL.checkIfFullMember(uuid) == true && nextShift.equals(playerShift) && mySQL.getShiftNo(uuid) > 0){
    35. shiftHandler[i] = new ShiftHandler(plugin, onlinePlayers[i], true).runTaskLater(plugin, i*20);
    36. logger.info(onlinePlayers[i].getName());
    37. }
    38.  
    39. //tp player home
    40. else if(mySQL.checkIfFullMember(uuid) == true && !nextShift.equals(playerShift) && mySQL.getShiftNo(uuid) > 0){
    41. shiftHandler[i] = new ShiftHandler(plugin, onlinePlayers[i], false).runTaskLater(plugin, i*20);
    42. logger.info(onlinePlayers[i].getName());
    43. }
    44. }
    45.  
    46. //advance to next shift
    47. if(nextShift.equals("sunset"))
    48. nextShift = "sunrise";
    49. else
    50. nextShift = "sunset";
    51. }
    52.  
    53.  
    54. }[/i][/i][/i][/i][/i][/i][/i][/i]


    I've used a BukkitTask array to store a new instance of ShiftHandler each loop. I don't understand why the player object in ShiftHandler appears to be overridden when the new instance of ShiftHandler is stored in a different position in the array?

    ShiftHandler:
    Code:java
    1. public class ShiftHandler extends BukkitRunnable {
    2.  
    3. private final JavaPlugin plugin;
    4. public final Logger logger = Logger.getLogger("Minecraft");
    5.  
    6. private static Player player;
    7. public static MySQL mySQL = new MySQL();
    8. public static boolean tpWork;
    9.  
    10. public ShiftHandler(JavaPlugin plugin, Player player, boolean tpWork) {
    11. this.plugin = plugin;
    12. this.player = player;
    13. this.tpWork = tpWork;
    14. }
    15.  
    16. @Override
    17. public void run() {
    18. logger.info(player.getName());
    19. if(player.isOnline() == true){
    20. if(tpWork == true && mySQL.getOnShift(player.getUniqueId().toString()) == false) //check to make sure player didn't leave and join again before being TP'd (prevent conflict with onJoin check)
    21. tpPlayerToWork();
    22. else if(tpWork == false && mySQL.getOnShift(player.getUniqueId().toString()) == true) //check to make sure player didn't leave and join again before being TP'd (prevent conflict with onJoin check)
    23. tpPlayerHome();
    24. }
    25. }...


    To put it simply, I want each new instance of ShiftHandler to be its own object. The player and tpWork variables in each new instance of ShiftHandler must be unique. At the moment it seems like each time a new instance of ShiftHandler is created, it's just updating the same instance.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
  2. Offline

    Niknea

    Brut Each BukkitScheduler has an ID. So you can store each schedulers ID in a HashMap, to later retrieve it.
     
    xYourFreindx likes this.
  3. Offline

    mythbusterma

    Brut

    You should really stop abusing those statics so much, it seems to be making your issues much harder to find. Also, instead of an array, you should consider using a map. Instead of using "final logger = getLogger("Minecraft") you should instead ask the plugin for the logger via getLogger().
     
    mine-care likes this.
  4. Offline

    Brut

    @Niknea
    @mythbusterma

    I've tidied the ShiftScheduler up a bit by changing some global variables to local variables and using plugin.getLogger() instead. I'm not familiar with Maps or HashMaps, but I seem to have got a HashMap working with the ShiftScheduler.

    Still hasn't solved my problem. The scheduled tasks will execute on time but they only contain the data of the last player to be processed by the for loop. Each scheduled task should be unique to each person on the server that satisfies the if or else if statement in the for loop.

    ShiftScheduler:
    Code:java
    1. mySQL = new MySQL();
    2.  
    3. String playerShift = "";
    4. String uuid = "";
    5. Player[] onlinePlayers = Bukkit.getOnlinePlayers();
    6. int noOfPlayers = onlinePlayers.length;
    7. HashMap<String, BukkitTask> taskID = new HashMap<String, BukkitTask>();
    8.  
    9. for(int i=0; i<noOfPlayers; i++){
    10. playerShift = mySQL.getShift(onlinePlayers[i].getUniqueId().toString());
    11. uuid = onlinePlayers[i].getUniqueId().toString();
    12.  
    13. //tp player to work
    14. if(mySQL.checkIfFullMember(uuid) == true && nextShift.equals(playerShift) && mySQL.getShiftNo(uuid) > 0){
    15. taskID.put(onlinePlayers[i].getName(), new ShiftHandler(plugin, onlinePlayers[i], true).runTaskLater(plugin, i*20));
    16. plugin.getLogger().info(onlinePlayers[i].getName());
    17. }
    18.  
    19. //tp player home
    20. else if(mySQL.checkIfFullMember(uuid) == true && !nextShift.equals(playerShift) && mySQL.getShiftNo(uuid) > 0){
    21. taskID.put(onlinePlayers[i].getName(), new ShiftHandler(plugin, onlinePlayers[i], false).runTaskLater(plugin, i*20));
    22. plugin.getLogger().info(onlinePlayers[i].getName());
    23. }
    24.  
    25. }[/i][/i][/i][/i][/i][/i][/i][/i]
     
  5. Offline

    mythbusterma

    Brut

    Because it looks like you're declaring the Map inside of "run()" which means each time you run the task, it creates a new HashMap, and when you try to use it, it will only find one entry, the last one you made.
     
  6. Offline

    Brut

    @mythbusterma

    So the HashMap should be declared globally? Just tried that, doesn't make a difference.

    Console log:
    Code:
    [21:21:37] [Server thread/INFO]: [<pl name>] <player 1>
    [21:21:37] [Server thread/INFO]: [<pl name>] <player 2>
    [21:21:37] [Server thread/INFO]: <player 2>  <--- This should be <player 1>
    [21:21:38] [Server thread/INFO]: <player 2>  
    That's the console log highlighting the problem (I've removed names for privacy reasons).

    Current ShiftScheduler:
    Code:java
    1. public class ShiftScheduler extends BukkitRunnable {
    2.  
    3. private final JavaPlugin plugin;
    4.  
    5. public static MySQL mySQL;
    6. public static String nextShift = "";
    7. public HashMap<String, BukkitTask> taskID = new HashMap<String, BukkitTask>();
    8.  
    9. public ShiftScheduler(JavaPlugin plugin, String nextShift) {
    10. this.plugin = plugin;
    11. this.nextShift = nextShift;
    12. }
    13.  
    14. @Override
    15. public void run() {
    16. mySQL = new MySQL();
    17.  
    18. String playerShift = "";
    19. String uuid = "";
    20. Player[] onlinePlayers = Bukkit.getOnlinePlayers();
    21. int noOfPlayers = onlinePlayers.length;
    22.  
    23. for(int i=0; i<noOfPlayers; i++){
    24. playerShift = mySQL.getShift(onlinePlayers[i].getUniqueId().toString());
    25. uuid = onlinePlayers[i].getUniqueId().toString();
    26.  
    27. //tp player to work
    28. if(mySQL.checkIfFullMember(uuid) == true && nextShift.equals(playerShift) && mySQL.getShiftNo(uuid) > 0){
    29. taskID.put(onlinePlayers[i].getName(), new ShiftHandler(plugin, onlinePlayers[i], true).runTaskLater(plugin, i*20));
    30. plugin.getLogger().info(onlinePlayers[i].getName());
    31. }
    32.  
    33. //tp player home
    34. else if(mySQL.checkIfFullMember(uuid) == true && !nextShift.equals(playerShift) && mySQL.getShiftNo(uuid) > 0){
    35. taskID.put(onlinePlayers[i].getName(), new ShiftHandler(plugin, onlinePlayers[i], false).runTaskLater(plugin, i*20));
    36. plugin.getLogger().info(onlinePlayers[i].getName());
    37. }
    38.  
    39. }
    40.  
    41. //advance to next shift
    42. if(nextShift.equals("sunset"))
    43. nextShift = "sunrise";
    44. else
    45. nextShift = "sunset";
    46. }
    47. }[/i][/i][/i][/i][/i][/i][/i][/i]
     
  7. Offline

    Brut

    Finally got it working, although not in the way I would have liked. I've had to add each player object and boolean into an array, then assign the current position in the array to the normal variables.

    New ShiftHandler:
    Code:java
    1. public class ShiftHandler extends BukkitRunnable {
    2.  
    3. private final JavaPlugin plugin;
    4. public final Logger logger = Logger.getLogger("Minecraft");
    5.  
    6. private static Player player;
    7. public static MySQL mySQL = new MySQL();
    8. public static boolean tpWork;
    9.  
    10. public boolean[] tpWorkArray = new boolean[50];
    11. public Player[] playerArray = new Player[50];
    12. public static int counter = 0;
    13.  
    14. public ShiftHandler(JavaPlugin plugin, Player player, boolean tpWork) {
    15. this.plugin = plugin;
    16. playerArray[counter] = player;
    17. tpWorkArray[counter] = tpWork;
    18. //this.player = player;
    19. //this.tpWork = tpWork;
    20. }
    21.  
    22. @Override
    23. public void run() {
    24. player = playerArray[counter];
    25. tpWork = tpWorkArray[counter];
    26. logger.info(player.getName() + " " + tpWork);
    27.  
    28. if(player.isOnline() == true){
    29. if(tpWork == true && mySQL.getOnShift(player.getUniqueId().toString()) == false) //check to make sure player didn't leave and join again before being TP'd (prevent conflict with onJoin check)
    30. tpPlayerToWork();
    31. else if(tpWork == false && mySQL.getOnShift(player.getUniqueId().toString()) == true) //check to make sure player didn't leave and join again before being TP'd (prevent conflict with onJoin check)
    32. tpPlayerHome();
    33. }
    34.  
    35. counter++;
    36.  
    37. if(playerArray[counter] == null)
    38. reset();
    39. }


    I know it at least works with two players, but I'm having trouble getting more than two players on at a time. Feel free to join:

    <mod edit-removed advertising>
     
Thread Status:
Not open for further replies.

Share This Page