(Deprecated) Bukkit's Standard Configuration Tutorial

Discussion in 'Resources' started by captainawesome7, Jul 11, 2011.

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

    captainawesome7

    Please Read Me
    Well I don't know why but alot of people have been either confused or just badly informed when it comes to making config files (*cough* HUGE plugin tutorial *cough*). To make a config you don't need any sort of readers, input streams, or FileNotFoundException catchers. Bukkit's standard configuration is an extremely easy to use system that for some reason just isn't widely publicized. If you aren't a Java n00b please note that this tutorial was written with the utter n00b in mind :)

    Getting Started
    The best way to add config support is to create a public Configuration variable. Obviously you are going to have to import the following:
    Code:
    import org.bukkit.util.config.Configuration;
    The next step branches off in two directions. If you have a basic plugin which stores a few values that already exist (have default values), do the following:

    Basic Configs
    To make a basic config all you have to do is create a few public variables and set them in onEnable(). The process basically resembles this:
    Code:
    //The config
    public Configuration config;
    
    //Add variables that the user can define. We'll add one each of common types:
    public Boolean configBoolean;
    public String configString;
    public Integer configInt;
    
    //Add this into your already existing onEnable:
    public void onEnable() {
        config = getConfiguration(); //Sets the public config to the /plugins/PluginFolder/config.yml
        config.load(); //Load the config
        configString = config.getString("String", "This is a String!"); //Gets the string, and if none found sets it to This is a String!
        configBoolean = config.getBoolean("Boolean", true); //Gets the boolean, if none found sets it to true
        configInt = config.getInt("Integer", 0); //Gets the integer, if none found sets it to 0
        config.save(); //Save the config!
    }
    All that we did above is load some values from a config file. You can create your own config loading and saving methods to allow configuration reloading without reloading the server (located at the bottom).

    User Added Content Configs
    This method should be used when you want the user to be able to add their own content into the config (see BCMusic or Achievement). This method is easy as well, but it isn't necessary for most plugins. The setup is basically the same as above, but this time I will provide an example of when this would be used (instead of the other way). The basic code (with comments) is:
    Code:
    public Configuration config; //Set the config
    
    public void onEnable() {
        config = getConfiguration(); //Get the config file from /plugins/PluginFolder/config.yml
    }
    
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if(!(sender instanceof Player)) {
            return false;
        }
        Player player = (Player) sender;
        if(label.equalsIgnoreCase("config")){ //if the command is "config" (just an example):
            //Gets the string for the player's name that is set in the config.
            String message = config.getString(player.getName(), "null"); //Default is "null"
            //If the message is null they don't have one in the conifg, let them know
            if(message.equals("null")) {
                player.sendMessage("There is no messagae for you set in the config!");
                return true;
            }
            //If they do have a message in the config, send it to them.
            player.sendMessage(message);
            return true;
        }
        return false;
    }
    That was just an example of when the user needs to be able to set their own values that they come up with. In the context of Achievement it allows them to create their own achievements, or in BCMusic they can add their own song.

    Saving/Loading Configs
    If you want to be able to save/reload your config with a command you can just put the following method in and call it when a player types whatever command.
    For use with the first (Basic) config method. This one saves the config (lets players change the values in game via command and be saved when they reload the config):
    Code:
    public void reloadConfig() {
        //Save
        config.setProperty("String", configString);
        config.setProperty("Boolean", configBoolean);
        config.setProperty("Integer", configInt);
        config.save();
        //Reload
        config = new Configuration(new File(getDataFolder().getPath() + "/config.yml"));
        config.load();
        configString = config.getString("String", "This is a String!");
        configBoolean = config.getBoolean("Boolean", true);
        configInt = config.getInt("Integer", 0);
    }
    This next method reloads the config when the player has to add content to the config himself (User Added Content). It only reloads the config, it doesn't save any values:
    Code:
    public void reloadConfig() {
        config = new Configuration(new File(getDataFolder().getPath() + "/config.yml"));
    }
    Adding Comments:
    If, for whatever reason, you don't think your users are capable of understanding the configuration file you have created, you can add comments using setHeader(). An example of this (and what it looks like in the file) is below. If you don't use a # before your header, it may confuse the header with a value that starts with the same few letters.
    How to add a comment using setHeader():
    Code:
    config.setHeader("#This will be at the top of the config file.");
    config.save();
    The code above will make the config.yml (Basic) look like this:
    Code:
    This will be at the top of the config file.
    String: string here
    Integer: 0
    Boolean: false
    
    Thats About It!
    If you have any questions about what was done above don't hesitate to ask. The only reason I wrote this was to let people know that you don't need to deal with prop.put(), IOExceptions, FileNotFoundExceptions, and all of that messy stuff. This is just an easy alternative that Bukkit has provided us, and I encourage you to use it :)

    WHY XENFORO!?!?! WHY DID U RUIN MY BEAUTIFULLY FORMATTED POST!??!?!

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

    chernobyl360

    lol wow thats awful! why did it kill you post? anyways Thanks for the tutorial. this is definitely more organized then "Adamsk11s huge tutorial" config section.
     
  3. Offline

    captainawesome7

    Yeah it messed up a code block and put in 400 LEFT tags :/ I fixed it with find+replace in a few minutes.
    I agree though, the HUGE tutorial's main problem is that it is too big for one post. He needs to split it up
     
  4. Offline

    Matterz

    How to add comments to the config.yml to help users?
     
  5. Offline

    captainawesome7

    You shouldn't need to use comments, and if you do just copy the config that is auto created and put it in your plugin's OP with comments added.
    Or you can use config.setHeader("Path here", "comment here");

     
  6. Offline

    DrBowe

    the setHeader(<path>) will do this

    EDIT:
    Also, bravo on this, captain.
    I was beginning to scratch my head as to why people would go to the trouble of IO streams, when this is monumentally simpler. Was planning to write this myself, but this is fantastic.
     
  7. Offline

    captainawesome7

    Thanks, and I completely forgot about config.setHeader() when writing this, I'm going to go add it now.
     
  8. Offline

    Matterz

    One more question. If I want to use a List<String> how do I set defaults?

    Code:
    public Configuration config;
    public Double damageFactor;
    public List<String> materials;
    private List<String> defaultMaterials;
    
    	@Override
    	public void onEnable() {
    
         defaultMaterials.add("STICK");
         defaultMaterials.add("STONE_AXE");
    
           config = getConfiguration();
           damageFactor = config.getDouble("damageFactor", 1.1);
           materials = config.getStringList("Materials", defaultMaterials);
           config.save();
    	}
    Is this the best way?
     
  9. Offline

    captainawesome7

    @Matterz Yeah. I think that should work fine.
     
  10. Offline

    DrBowe

    Hrm. I seem to have mis-described it, however. It doesn't allow you to set paths (apparently), so it can only go at the very top of the configuration file...

    I actually wouldn't mind if they implemented a config.setHeader("general.derp", String header) method...might put something up in the repo about that
     
  11. Offline

    Matterz

    If I want to call these from another class do I need to add a get method?

    Like in my main class I would add:

    Code:
    public List<String> getMaterials(){
            return this.materials;
        }
    
    public Double getDamageFactor(){
         return this.damageFactor;
    }
    Sorry for newb questions. No formal Java training :(
     
  12. Offline

    captainawesome7

    Yeah i just figured that out as well..

    Nooo just make them public. Then (if you set up instances correctly) use plugin.damageFactor etc.

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

    DrBowe

    I prefer protected static, but that's just me :p
     
  14. Offline

    Matterz

    So Everything seems to be working well with my config.yml except the StringList... Not sure what I am doing wrong.

    Code:java
    1. public class SNConfigHandler {
    2. public static SNPlugin plugin;
    3. //Config variables
    4. public Configuration config;
    5. public static double damageFactor;
    6. public static List<String> materials = new ArrayList<String>();
    7. private List<String> defaultmaterials = new ArrayList<String>();
    8. public static double damageReceivedFactor;
    9. public static double deltaSpeed;
    10. public static int maxPower;
    11. public static int timerInterval;
    12.  
    13. public SNConfigHandler(SNPlugin instance){
    14. SNConfigHandler.plugin = instance;
    15. }
    16.  
    17. public void getConfiguration(){
    18.  
    19. defaultMaterials.add("APPLE");
    20. defaultMaterials.add("BREAD");
    21. defaultMaterials.add("COOKED_FISH");
    22. defaultMaterials.add("GRILLED_PORK");
    23. defaultMaterials.add("GOLDEN_APPLE");
    24. defaultMaterials.add("MUSHROOM_SOUP");
    25. defaultMaterials.add("RAW_FISH");
    26. defaultMaterials.add("PORK");
    27.  
    28. config = plugin.getConfiguration();
    29. damageFactor = config.getDouble("Damage.Factor", 1.1);
    30. materials = config.getStringList("Materials", defaultMaterials);
    31. damageReceivedFactor = config.getDouble("Damage.ReceivedFactor", 0.9);
    32. deltaSpeed = config.getDouble("DeltaSpeed", 3);
    33. maxPower = config.getInt("MaxAllowedPower", 10000);
    34. timerInterval = config.getInt("TimerInterval", 30000);
    35. config.save();
    36. }
    37. }


    This Code yields the following config.yml

    Code:
    MaxAllowedPower: 10000
    Damage:
            ReceivedFactor: 0.9
            Factor: 1.1
    DeltaSpeed: 3.0
    TimerInterval: 1000
    What am I doing wrong with config.getStringList??
     
  15. Offline

    DreadKyller

    are you getting any errors?
     
  16. Offline

    Matterz

    Not on server startup/shutdown.

    I haven't really worked with the plugin too much yet to flush everything out though.
     
  17. Offline

    captainawesome7

    I'm not sure that setting a default list works very well. Try setting the default to null and just putting the list in yourself.
     
  18. Offline

    DrBowe

    String lists are tricky to initialize the first time a plugin loads.
    Give me just a second, I'll post a quick snippet of what I used to fix this in my PvPable plugin.

    EDIT:
    Code:java
    1.  
    2. protected static List<String> RESTRICTED_COMMANDS;
    3.  


    In the loadConfig() method:
    Code:java
    1.  
    2. RESTRICTED_COMMANDS = config.getStringList("CommandRestriction.Restricted-Commands", null);
    3. if(RESTRICTED_COMMANDS.size() == 0){
    4. RESTRICTED_COMMANDS.add("command1");
    5. config.setProperty("CommandRestriction.Restricted-Commands", RESTRICTED_COMMANDS);
    6. }
    7.  

    Essentially, you have to check to see if the list is empty (which it will be the first time anyone loads it), and then place atleast 1 'example' string into this list. This is the only way I've managed to successfully show a String-List without the user having to create it themselves.

    Granted, I didnt try any other methods after I learned this works, soooo :p
     
    Chromana likes this.
  19. Offline

    Matterz

    That works. Thanks
     
  20. Offline

    DrBowe

    Glad I could help :)
     
  21. Offline

    wouter0100

    can i make a custom name like;
    Code:
    config = getConfiguration("[pad]/[name].yml");
    
     
  22. Offline

    DreadKyller

    @wouter0100 you can just you will not use getConfiguration()

    Code:java
    1. public Configuration getConfigFromPath(String path){
    2. public File file = new File(path);
    3. file.getParentFile().mkdirs();
    4. if(!file.exists()){
    5. try{
    6. file.createNewFile();
    7. }catch(IOException e){
    8. System.out.println("configuration failed to load : "+e);
    9. }
    10. }
    11. public configuration config = new Configuration(file);
    12. config.load();
    13. return config;
    14. }
     
  23. Offline

    PatrickFreed

    Main
    EntityListener

    It's not loading correctly from the config or something. It always defaults to the else on line 59 of Entity Listener.
    Someone care to help a n00b?
     
  24. Offline

    PatrickFreed

    @captainawesome7

    disregard the last post, it just further proves my noobishness.

    Now I have a slight problem, my config.yml generates like this:
    Code:
    Static-amount: 150
    Min-Percentage: 1
    Max-Amount: 100
    attacker-msg: You earn %n for killing %d
    Max-Percentage: 25
    Static-percentage: 5
    Min-Amount: 2
    Mode: Random Amount
    dead-msg: You lose %n for being killed by %a
    but I want to generate like I have in the code:

    PHP:
        mode config.getString("Mode""Static Amount");
        
    death_msg config.getString("dead-msg""You lose %n for being killed by %a");
        
    kill_msg config.getString("attacker-msg""You earn %n for killing %d");
        
    maxP config.getInt("Max-Percentage"25);
        
    minP config.getInt("Min-Percentage"1);
        
    maxA config.getInt("Max-Amount"50);
        
    minA config.getInt("Min-Amount"1);
        
    staticAmount config.getInt("Static-amount"15);
        
    staticPercentage config.getInt("Static-percentage"5);
    Also, how should I go about adding comments? Thanks!
     
  25. Offline

    captainawesome7

    @PatrickFreed Do you mean the order of the values in the file?
     
  26. Offline

    PatrickFreed

    Yeah, you can see in the code "Mode" comes first, but in the config it comes second to last.
     
  27. Offline

    wouter0100

    I have found a little spelling mistake.
    //Reoad
    //Reload
     
  28. Offline

    captainawesome7

    While fixing this XenForo decided to screw me over and ruin my post :(
     
  29. Offline

    Fabis94

    Hm, for some reason a config file isn't created with this code, for me :/
     
  30. Offline

    captainawesome7

    For some reason, huh?
     
Thread Status:
Not open for further replies.

Share This Page