World = Null?

Discussion in 'Plugin Development' started by Tyler Christensen, Apr 10, 2015.

Thread Status:
Not open for further replies.
  1. So i have a spawn plugin, onEnable, it gets all the locations from a config list, and sets them to a regular list. From there, is a player joins, or types /spawn, it gets a spawn form the list, and teleports the player to it. However, on the plugin first enable, any spawn but the, the world is null, but if i reload the plugin... Everything turns out perfectly. Any ideas? Here is all my classes.

    Main Class:
    Code:
    package net.extronicgaming.extrospawns;
    
    import java.util.ArrayList;
    import java.util.List;
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class ExtroSpawnsPlugin extends JavaPlugin{
        private static ExtroSpawnsPlugin instance;
        public static ExtroSpawnsPlugin getInstance(){return instance;}
        public static List<Location> spawns = new ArrayList<Location>();
        @Override
        public void onEnable(){
            saveDefaultConfig();
            commands();
            registerListeners();
            spawns.clear();
            setupLocations();   
        }
       
        @Override
        public void onDisable(){
            spawns.clear();
        }
       
        public void registerListeners(){
            Bukkit.getServer().getPluginManager().registerEvents(new Eventlistener(this), this);
        }
       
        public void commands(){
            this.getCommand("spawn").setExecutor(new Commands(this));
        }
       
       
       
        public void setupLocations(){
             for(String s :getConfig().getStringList("Spawns")){
                 Location location = deserialize(s);
                 if(location != null)
                     spawns.add(location);
             }
             Locationutilities.n = spawns.size();
             Locationutilities.i = 0;
        }
       
       
       
       
        public static Location deserialize(String s){
            try{
              String[] data = s.split(":");
              Location l = new Location(Bukkit.getWorld(data[0]), Double.parseDouble(data[1]), Double.parseDouble(data[2]), Double.parseDouble(data[3]), Float.parseFloat(data[4]), Float.parseFloat(data[5]));
              return l;
            }catch(Exception e){
                  return null;
              }
        }
    }
    
    Listener Class:
    Code:
    package net.extronicgaming.extrospawns;
    
    import org.bukkit.ChatColor;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.event.player.PlayerRespawnEvent;
    
    public class Eventlistener implements Listener{
        public Eventlistener(ExtroSpawnsPlugin pl){
        }
        @EventHandler(priority = EventPriority.MONITOR)
        public void onPlayerJoinEvent(PlayerJoinEvent event){
            event.getPlayer().sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.GREEN + "ExtronicGaming" + ChatColor.DARK_GRAY + "]" + ChatColor.YELLOW + " Welcome!");
            event.setJoinMessage("");
            try{
            Locationutilities.teleportToSpawn(event.getPlayer());
            } catch (Exception e){
                e.printStackTrace();
            }
        }
        @EventHandler(priority = EventPriority.MONITOR)
        public void onPlayerRespawnEvent(PlayerRespawnEvent event){
            event.setRespawnLocation(Locationutilities.newSpawnLocation());
        }
       
        @EventHandler(priority = EventPriority.MONITOR)
        public void onPlayerQuitEvent(PlayerQuitEvent event){
            event.setQuitMessage("");
        }
    }
    
    Commands Class:
    Code:
    package net.extronicgaming.extrospawns;
    
    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.entity.Player;
    
    public class Commands implements CommandExecutor{
        ExtroSpawnsPlugin plugin;
        public Commands(ExtroSpawnsPlugin plugin){this.plugin = plugin;}
        @Override
        public boolean onCommand(CommandSender Sender, Command cmd, String commandLabel, String[] args) {
            if(Sender instanceof Player){
                Player player = (Player)Sender;
                if(commandLabel.equalsIgnoreCase("spawn")){
                    Locationutilities.teleportToSpawn(player);
                }
            }else{
                Sender.sendMessage(ChatColor.DARK_RED + "You must be a player to use these commands!");
            }
            return false;
        }
    }
    
    And my Locationutilities Class:

    Code:
    package net.extronicgaming.extrospawns;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.entity.Player;
    
    public class Locationutilities {
        static int n;
        static int i = 0;
       
       
        public static void teleportToSpawn(Player player) {
            i++;
            if(i>=n){
                i = 0;
            }
            Location spawn = ExtroSpawnsPlugin.spawns.get(i);
            Bukkit.broadcastMessage(spawn.toString() + "");
            player.teleport(spawn);
        }
       
       
       
       
        public static Location newSpawnLocation() {
            Location l = ExtroSpawnsPlugin.spawns.get(i);
            i++;
            if(i>=n)
                i=0;
            return l;
        }
       
       
    }
    
    Any help would be appriciated! <3
     
  2. Offline

    mine-care

    Oh please! dont abuse static! (Not to mention Locationutilities class)
    Here you are doing it properly but you take the argument by the constructor and do nothing with it?

    Setting message to "" on join or leave will make it display a empty line, use null.
    prefer to catch the specific exception thrown, here ArrayIndexOutOfBoundsException and NumberFormatException

    Have you debuged? errors in console?
     
    Tyler Christensen likes this.
  3. Offline

    caderape

    @Tyler Christensen
    May be cuz the world is not loaded yet when your plugin is loading.
     
  4. Offline

    Zombie_Striker

    Try instead of saving the entire location in one spot, make for pathways labels "x,y,z,w" where x is the X, y is the Y, z is the Z, and w is the World.getName.

    Then, for constuction the location for the spawns, Make a new Location(getServer().getWorld(w),x,y,z);
     

  5. So first off, i would like to thank you for pointing out so many errors i have in my code <3 Secondly, I have debugged, and it spawns me to the world, on the first player join, or the first /spawn command. However, after that, the other locations = null.


    @caderape The issue can't be if the world is loaded or not, all it is dealing with is getting the strings from the config, and storing them in a list. I only use the actual location once a player joins, or types a command. So it isnt the world.

    @Zombie_Striker The issue with that is because i have it in a list, its more than just one spawn location.

    Now My thoughts on this whole thing: Maybe should i keep track of an int, and add onto it every time i get a spawn location.
    I would get a spawn location from the config string list every time a player joins/runs the spawn command, instead of how i have it now, where i have all the spawns pre-loaded into a list. What do you guys suggest?
     
  6. Offline

    mine-care

    @Tyler Christensen i would say no because constantly getting from the config is inefficient (Small difference but...), i would recomend the loading as you do it, and a litle further debug to find out what turns null at what occasion, then you are able to proceed with fixing it. =)
     
  7. Ya, i did as much debugging as i can, its really strange.
     
  8. Offline

    Zombie_Striker

    Well @Tyler Christensen , You could extend the path further by adding (path.1.x and path.2.x) If you have multiple spawns.
     
  9. Its a string list, not an actual path. the config looks like:


    Spawns:
    - 'Main:340:120:-1345:0:0'
    - 'Spawn:0.5:103:0.5:0:0'
     
  10. Offline

    Funergy

    The private static's are not a problem but the public's are.
     
  11. @Funergy Privates can be a problem. And why static if you are just using it as a private variable.
     
  12. Offline

    Funergy

    @bwfcwalshy
    mostly used for

    private static GameManager instance;
    public void onEnable(){instance = new GameManager();}
    public static GameManager getInstance(){return instance;}
     
  13. Offline

    mine-care

    @Funergy even with private it makes no sense, it is an abuse Because the main class cannot be instanciated more than once so why attepting to keep a variable the same between instances makes absolutely no sense at all.also about getting the instance I recomend the use of constructors to pass it :- )
     
    Tyler Christensen likes this.
  14. Offline

    Konato_K

    @Funergy Considering how you put "onEnable", that will throw an error if done in a JavaPlugin class
     
  15. Offline

    mythbusterma

    The ConfigurationSections are backed by HashMaps in memory, what is more or less the fastest general purpose structure, so I don't know what you're on about.

    It's a design pattern called "singleton," look it up sometime (that being said, @Funergy did it completely wrong).


    @Tyler Christensen

    Show the updated code.
     
  16. Offline

    mine-care

    @mythbusterma true :/ mainly focused on the loading/saving because when configs are used their saving/loading/reloading abilities are also used and some times abused so in order to avoid such a thing i recomend alterantive storage methods when possible.

    :O didnt know about that! Thanks!
     
  17. Offline

    Funergy

    @mythbusterma Oh sorry people told me that earlier (In a YT-er stream). Thats why I stopped watching Youtubers creating plugins.
    But anyways thanks for the clarification.

    @Konato_K Tell me why it should give an error. Thats the way I do it, and it never gave me any error.
     
    Last edited by a moderator: Apr 12, 2015
  18. Offline

    Konato_K

    @Funergy It will because you're creating a new instance of the JavaPlugin subclass.
     
  19. Offline

    mythbusterma

    @Funergy @mine-care

    For the record, here is one implemented properly:

    Code:
    public class Singleton {
    
           private static Singleton instance;
    
           public static Singleton getInstance () {
                 if (instance == null ) {
                       instance = new Singleton();
                  }
                  return instance;
            }
    }
    In the case of a Bukkit plugin, since you can't instantiate your own plugin, but it won't be used before onEnable (or onLoad):

    Code:
    public class BukkitSingleton extends JavaPlugin {
    
          private static BukkitSingleton instance;
    
          @Override
          public void onEnable() {
               instance = this;
               /* etc */
          }
    
          public static BukkitSingleton getInstance() {
                return instance;
          }
    }
     
  20. Offline

    ItsMattHogan

    snip
     
    Last edited: Apr 16, 2015
  21. Offline

    Konato_K

    Adding on the Singleton Pattern, it's good to make the class final so it can't be overriden, have only a private constructor and override Object#clone aswell.
     
  22. Lol this is an intresting conversation xD But this still does not answer my question, and why does it work after i /reload But not on first startup. That is why this confuses me....
     
  23. Offline

    Konato_K

    @Tyler Christensen Ah! Probably the worlds are unloaded before your plugin initializes the first time, try to load your plugin AFTER whatever plugin is loading the worlds (Multiverse?)
     
  24. Its not that the worlds arent loaded, its saving them as a string, and ONLY converts them to an actual locatin once the player logs in or type /command.
     
  25. Code:
    World world = Bukkit.getWorld("world");
    if(world != null) { }
    
    I don't know if this code is going to work, i never have done something like this.

    If this still throwing a NPE

    Try with this
    Code:
    String worldname = "world";
    World world = null;
    
    for(World w : Bukkit.getWorlds()) {
         if(w.getName().equals(worldname)) {
              world = w;
              break;
          }
    }
    
    if(world != null) { }
    
     
    Last edited: Apr 15, 2015
    iLalox likes this.
  26. Nope. The instance variable is never set here, so it will always be null, thus returning a new Singleton instance every time - the opposite of what a singleton is!
     
  27. Offline

    ItsMattHogan

    oh, whoops.
     
Thread Status:
Not open for further replies.

Share This Page