Config from another class

Discussion in 'Resources' started by theguynextdoor, Feb 25, 2012.

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

    theguynextdoor

    I know i have this as a small section in my other config tutorial, but in this tutorial i will go into more detail and tell you everything you need to make this work because recently i have seen a few people who have a small problem which can easily be fixed but it's nice not to have the errors to start with.

    This is a tutorial for new developers (i hope experienced devs dont have this problem :p, not that it would matter of they do) and so i will break it down as much as i can.

    So to start off we shall make a very basic main class.

    Code:java
    1. public class ConfigExample extends JavaPlugin {
    2.  
    3. @Override
    4. public void onDisable() {
    5.  
    6. }
    7.  
    8. @Override
    9. public void onEnable() {
    10.  
    11. }
    12. }


    Ok, what this plugin will do is it will send a player a message which is defined in the config when they log in, or when they use the command we will make.

    So to start off, we shall make our config in our onEnable method

    Code:java
    1. public class ConfigExample extends JavaPlugin {
    2.  
    3. @Override
    4. public void onDisable() {
    5.  
    6. }
    7.  
    8. @Override
    9. public void onEnable() {
    10.  
    11. final FileConfiguration config = this.getConfig();
    12.  
    13. config.addDefault("Message.to.send", "Hello, this is our message to send");
    14.  
    15. config.options().copyDefaults(true);
    16. saveConfig();
    17. }
    18.  
    19. }


    Just to break it down,
    Code:java
    1. final FileConfiguration config = this.getConfig();

    this line is defining our config so we can use it.

    Code:java
    1. config.addDefault("Message.to.send", "Hello, this is our message to send");

    this line is adding a default line when the config is made, with the path Message.to.send and a string value.

    Code:java
    1. config.options().copyDefaults(true);
    2. saveConfig();

    When a config is made, it initially is blank, but when you have these lines, they add in the defaults you have specified above.

    Ok, now we shall make a listener, so we can send the message to a player who joins the server.
    Note: this is a separate class.

    Right, before i go rushing off to make the event bit, i want to emphasize the constructor. Most people when they make a separate listener, will have their plugin variable, but they wont assign it to anything. And so what the constructor is doing, is assigning that plugin variable to our main class.

    Note: without the constructor, your plugin variable will return null and you WILL get a Nullpointer Exception.

    Code:java
    1. public class ConfigListener implements Listener{
    2. ConfigExample plugin;
    3.  
    4. public ConfigListener(ConfigExample instance) {
    5. plugin = instance;
    6. }
    7.  
    8. }


    Ok, so now that the constructor is sorted, we can move on to sending the message to the player when they log onto the server. To do this we are going to use a PlayerJoinEvent.

    Code:java
    1. public class ConfigListener implements Listener {
    2. ConfigExample plugin;
    3.  
    4. public ConfigListener(ConfigExample instance) {
    5. plugin = instance;
    6. }
    7.  
    8. @EventHandler
    9. public void onJoin(PlayerJoinEvent e) {
    10. Player player = e.getPlayer();
    11.  
    12. player.sendMessage(plugin.getConfig().getString("Message.to.send"));
    13. }
    14. }


    The lines:
    Code:java
    1. @EventHandler
    2. public void onJoin(PlayerJoinEvent e) {

    Are used to tell the plugin, 'Hey, we're going to use an event, of which is going to be a PlayerJoinEvent, and we have callled that event 'e'.

    Note how
    Code:java
    1. @EventHandler
    Doesnt have anything after it, this basically means that the event it is of default priority.

    The line:
    Code:java
    1. Player player = e.getPlayer();

    Is making a player variable, so whenever we type 'player' in our event, it will refer to the player that was involved in the event, which in this case is the person who logged on.

    The line:
    Code:java
    1. player.sendMessage(plugin.getConfig().getString("Message.to.send"));

    Is what we are using to send the message to our player.
    See here how we are getting our config:
    Code:java
    1. plugin.getConfig().getString("Message.to.send")

    we are referring to our plugin variable which we made earlier, and we are getting our string to send to the player from our config, by using
    Code:java
    1. getString("Message.to.send")

    The lines in the "", i.e the "Message.to.send" is the path to the variable in your config.

    Note how the path is the same as we made earlier:
    Code:java
    1. config.addDefault("Message.to.send", "Hello, this is our message to send");

    Code:java
    1. plugin.getConfig().getString("Message.to.send")

    If they were different, then we would not get the message we want.

    Now that we have our event and message set up, we should register our event in our onEnable, otherwise all our lovely code is made useless.

    To do this we simply do this:

    Code:java
    1. @Override
    2. public void onEnable() {
    3.  
    4. final FileConfiguration config = this.getConfig();
    5.  
    6. config.addDefault("Message.to.send", "Hello, this is our message to send");
    7.  
    8. config.options().copyDefaults(true);
    9. saveConfig();
    10.  
    11. PluginManager pm = getServer().getPluginManager();
    12. pm.registerEvents(new ConfigListener(this), this);
    13. }


    The lines which are registering the event and letting our beautiful code happen is:
    Code:java
    1. PluginManager pm = getServer().getPluginManager();
    2. pm.registerEvents(new ConfigListener(this), this);


    Note how i use registerEvents, this is registering all our events in our listener. This is particularly nice if were to have many events.

    Now lets export our plugin and see if it works so far:
    [​IMG]
    Yes, it does.

    Now, lets say we want to change that message in a command. How could we go about doing that? Well, lets make a new command:

    In our onEnable we shall add this

    Code:java
    1. getCommand("setmessage").setExecutor(new ConfigCommand(this));

    So your onEnable now looks something like this:
    Code:java
    1. @Override
    2. public void onEnable() {
    3.  
    4. final FileConfiguration config = this.getConfig();
    5.  
    6. config.addDefault("Message.to.send", "Hello, this is our message to send");
    7.  
    8. config.options().copyDefaults(true);
    9. saveConfig();
    10.  
    11. PluginManager pm = getServer().getPluginManager();
    12. pm.registerEvents(new ConfigListener(this), this);
    13.  
    14. getCommand("setmessage").setExecutor(new ConfigCommand(this));
    15. }


    Now, lets make our ConfigCommand class.

    now when i first make my class, it looks like this:
    Code:java
    1. package me.theguynextdoor.configexample;
    2.  
    3. import org.bukkit.command.Command;
    4. import org.bukkit.command.CommandExecutor;
    5. import org.bukkit.command.CommandSender;
    6.  
    7. public class ConfigCommand implements CommandExecutor {
    8.  
    9. @Override
    10. public boolean onCommand(CommandSender arg0, Command arg1, String arg2, String[] arg3) {
    11. // TODO Auto-generated method stub
    12. return false;
    13. }
    14.  
    15. }

    So, lets make our constructor and rename some of those command variable names. So it now looks something like:
    Code:java
    1. package me.theguynextdoor.configexample;
    2.  
    3. import org.bukkit.command.Command;
    4. import org.bukkit.command.CommandExecutor;
    5. import org.bukkit.command.CommandSender;
    6.  
    7. public class ConfigCommand implements CommandExecutor {
    8. ConfigExample plugin;
    9.  
    10. public ConfigCommand(ConfigExample instance) {
    11. plugin = instance;
    12. }
    13.  
    14. @Override
    15. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    16. return false;
    17. }
    18.  
    19. }


    Lets make our basic command then which will change the message in our config. The way this command will work is that it will set the message to anything you type after the command.

    The command once i had finished it looks like this:
    Code:java
    1. @Override
    2. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    3. if (cmd.getName().equalsIgnoreCase("setmessage")) {
    4. if (sender instanceof Player) {
    5.  
    6. if (args.length == 0) {
    7. return false;
    8. }
    9.  
    10. String msg;
    11.  
    12. StringBuilder sb = new StringBuilder();
    13. for (int i = 0; i < args.length; i++) {
    14. if (i != 0)
    15. sb.append(' ');
    16. sb.append(args);
    17. }
    18. msg = sb.toString();
    19.  
    20. sender.sendMessage("The message has been changed to: " + msg);
    21. plugin.getConfig().set("Message.to.send", msg);
    22. plugin.saveConfig();
    23.  
    24. return true;
    25. }
    26. }
    27. return false;
    28. }


    Now lets break down the command

    First off, i checked that the name of the command was setmessage, by doing a simple if statement:
    Code:java
    1. if (cmd.getName().equalsIgnoreCase("setmessage")) {


    After that i checked that the person who sent the command was a player, by doing another if statement:
    Code:java
    1. if (sender instanceof Player) {


    After that i checked that they actually typed something for their message by checking if the argument length was 0. Because if they argument length was 0 then they obviously didn't type anything. To do this, i typed:
    Code:java
    1. if (args.length == 0) {
    2. return false;
    3. }

    When i type return false, it tells the command that it didnt work right, and so the command will send the user the usage message which will be in the plugin.yml which i will get to in a second.

    Now, how do know how many arguments they put?
    Cant we just set the message to args[1] + args[2] ...
    The answer is no. So what we will be using is what is known as a string builder.

    The string builder looks like this:
    Code:java
    1. String msg;
    2.  
    3. StringBuilder sb = new StringBuilder();
    4. for (int i = 0; i < args.length; i++) {
    5. if (i != 0)
    6. sb.append(' ');
    7. sb.append(args);
    8. }
    9. msg = sb.toString();

    So now all we have to do, is set our Message.to.send variable in our config to msg.
    To do this we can simply do:
    Code:java
    1. plugin.getConfig().set("Message.to.send", msg);
    2. plugin.saveConfig();

    Note: You must not forget to do the plugin.saveConfig(); because without this the config will not save and your command might as well not be there.

    And just to assure the player that their command has worked, we will send them a little message:
    Code:java
    1. sender.sendMessage("The message has been changed to: " + msg);


    Now the command total looks like this:
    Code:java
    1. @Override
    2. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    3. if (cmd.getName().equalsIgnoreCase("setmessage")) {
    4. if (sender instanceof Player) {
    5.  
    6. if (args.length == 0) {
    7. return false;
    8. }
    9.  
    10. String msg;
    11.  
    12. StringBuilder sb = new StringBuilder();
    13. for (int i = 0; i < args.length; i++) {
    14. if (i != 0)
    15. sb.append(' ');
    16. sb.append(args);
    17. }
    18. msg = sb.toString();
    19.  
    20. sender.sendMessage("The message has been changed to: " + msg);
    21. plugin.getConfig().set("Message.to.send", msg);
    22. plugin.saveConfig();
    23.  
    24. return true;
    25. }
    26. }
    27. return false;
    28. }


    Now what we need to do is register the command in our plugin.yml

    This isnt a full plugin tutorial so i havent gone into the plugin.yml or how it works and what to put, but for this plugin my plugin.yml looks like this

    Code:
    name: ConfigExample
    main: me.theguynextdoor.configexample.ConfigExample
    version: 0.1
    commands:
        setmessage:
            description: sets the message to send
            usage: /<command> <message>
    Now we should be able to change the message:

    Before using the command:
    [​IMG]

    Just after typing our command:
    [​IMG]

    After relogging after typing command:
    [​IMG]


    ------------------------------------------------Extra------------------------------------------------------

    That is the main chunk of my tutorial done. Now what if we wanted colours?
    For colours: i.e when the player used &2 or &e they get colours. Doing this is rather simply.

    In our listener, when we send the message we add this to the end
    Code:java
    1. .replaceAll("(&([a-f0-9]))", "\u00A7$2")


    So our event now looks like this:
    Code:java
    1. @EventHandler
    2. public void onJoin(PlayerJoinEvent e) {
    3. Player player = e.getPlayer();
    4.  
    5. player.sendMessage(plugin.getConfig().getString("Message.to.send").replaceAll("(&([a-f0-9]))", "\u00A7$2"));
    6. }


    We also add this to our command,
    Code:java
    1. sender.sendMessage("The message has been changed to: " + msg.replaceAll("(&([a-f0-9]))", "\u00A7$2"));
    2. plugin.getConfig().set("Message.to.send", msg.replaceAll("(&([a-f0-9]))", "\u00A7$2"));


    So our final command executor looks like this:
    Code:java
    1. package me.theguynextdoor.configexample;
    2.  
    3. import org.bukkit.command.Command;
    4. import org.bukkit.command.CommandExecutor;
    5. import org.bukkit.command.CommandSender;
    6. import org.bukkit.entity.Player;
    7.  
    8. public class ConfigCommand implements CommandExecutor {
    9. ConfigExample plugin;
    10.  
    11. public ConfigCommand(ConfigExample instance) {
    12. plugin = instance;
    13. }
    14.  
    15. @Override
    16. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    17. if (cmd.getName().equalsIgnoreCase("setmessage")) {
    18. if (sender instanceof Player) {
    19.  
    20. if (args.length == 0) {
    21. return false;
    22. }
    23.  
    24. String msg;
    25.  
    26. StringBuilder sb = new StringBuilder();
    27. for (int i = 0; i < args.length; i++) {
    28. if (i != 0)
    29. sb.append(' ');
    30. sb.append(args);
    31. }
    32. msg = sb.toString();
    33.  
    34. sender.sendMessage("The message has been changed to: " + msg.replaceAll("(&([a-f0-9]))", "\u00A7$2"));
    35. plugin.getConfig().set("Message.to.send", msg.replaceAll("(&([a-f0-9]))", "\u00A7$2"));
    36. plugin.saveConfig();
    37.  
    38. return true;
    39. }
    40. }
    41. return false;
    42. }
    43. }


    So now:
    [​IMG]

    And when joining:
    [​IMG]


    Thanks for reading
     
    MarinD99, com. BOY, bballheat and 8 others like this.
  2. Offline

    CRAZYxMUNK3Y

    Nice work! Will definately refer to this in furture if i have some troubles :D
     
  3. Offline

    TopGear93

    I followed the exact steps to making the configs but eclipse is telling me that "config" in my listeners is "config cannot be resolved or is not a field".


    Edit:// I fixed it by doing a shortcut. Instead of putting

    Code:
    @Override
    public void onEnable(){
    final FileConfiguration config = this.getConfig();
    i had to do this


    Code:
    public static FileConfiguration config;
     
    @Override
    public void onEnable(){
    config = this.getConfig();
     
  4. Offline

    theguynextdoor

    What you should have put in your listener is:

    plugin.getConfig().getWhatEver("");
     
    TopGear93 likes this.
  5. Offline

    Lolmewn

    Holy crap, what a nice post.
    But what if I want to add comments to the config file? The Bukkit system tends to filter them out..
    I extract the file from the .jar, then edit some values. When just extracted, the comments are there, and when saving, the comments disappear.
     
  6. Offline

    theguynextdoor

    Thanks, but unfortunately when you save a config (in code i presume) then the comments get deleted. I wish there was a simple work around to this. I cant believe it isn't in the API at the moment, it should be pretty standard imo.
     
  7. Offline

    Lolmewn

    Yea, I agree. It's kinda a shame it's not possible. (if it is, I'll tell you)
     
  8. Offline

    CRAZYxMUNK3Y

    The only possible way is to type the config.yml yourself, then get they data from there (Not using config.addDefault();)
     
  9. Offline

    Lolmewn

    Yea, I do that. And then export the file. BUT when I edit data afterwards the comments get removed anyway :'(
     
  10. Offline

    Sagacious_Zed Bukkit Docs

    the Configuration API does not handle inline comments. It is working as expected per design of dinnerbone.
     
  11. Offline

    McLuke500

    This helped alot thanks :D
     
  12. Offline

    theguynextdoor

    Glad it helped
     
  13. Offline

    calebbfmv

    I have a question for you, I want my message to be sent when the player is kicked, like a kick reason, I have the main bit of code that kicks the player for asking for what I have in code, but now I want to have people be able to edit the groups they ask for/ the kickmessage. Any help?
     
  14. Offline

    SyTeck

    I'm using this, but I end up with a NPE..

    Code:
    AlternativeExp plugin;
     
        public Exp(AlternativeExp instance) {
     
            plugin = instance;
     
        }
    Then I use like

    Code:
    plugin.getConfig(). bla bla bla
    but I get this error:

    Code:
    Caused by: java.lang.NullPointerException
            at me.SyTeck.AlternativeExp.Exp.onCommand(Exp.java:48)
    Line 48:

    Code:
    if(plugin.getConfig().getBoolean("RandomMode") == true) {
    Any suggestion?

    Maybe its the random thingy I use, it looks like this:

    Code:
    Random rand = new Random();
                            int exp = rand.nextInt(11);
    but I don't think so.
     
  15. Offline

    theguynextdoor

    Since the error is in the onCommand, is there any chance i could see your whole main class, and command class?
     
  16. Offline

    SyTeck

    Ill send you a PM :)
     
  17. Offline

    theguynextdoor

    Sure, whatever suits you
     
  18. I have a problem similar to his...
    I'm using
    Code:java
    1. static Main plugin;
    2.  
    3. public commands(Main instance) {
    4. plugin = instance;
    5. }


    and I get an error for null pointer exception here:
    Code:
    static List<String> getEvents(){
    //line below this is errror
            if(plugin.getConfig().getConfigurationSection("EVENTS")==null){
                plugin.getConfig().createSection("EVENTS");
            }
            List<String> events = new ArrayList<String>();
            events.addAll(plugin.getConfig().getConfigurationSection("EVENTS").getKeys(false));
            return events;
        }
     
  19. Offline

    Compressions

  20. but if its not static Main plugin;
    it tells me I can't make a static reference to the non static field plugin...
     
  21. Offline

    Compressions

    XxShadow_NinjaxxX getConfig() will cause all kinds of issues if you call it in a static method. Start using constructors instead of static references for "convenience."
     
    AoH_Ruthless likes this.
  22. Offline

    negative_codezZ

    To add comments just do saveDefaultConfig(); instead of saveConfig();.
     
  23. Offline

    MCMastery

    theguynextdoor
    Why not use this:
    Code:java
    1. Plugin plugin = Bukkit.getPluginManager().getPlugin("YourPlugin");
    2. plugin.getConfig();
     
    WozzSWE likes this.
  24. Offline

    theguynextdoor

    MCMastery It is better from a design point of view to pass the instance because you can then access any other public methods in your main class, while your method would only allow for access to methods from the Plugin interface.
     
  25. Offline

    MCMastery

Thread Status:
Not open for further replies.

Share This Page