How to REALLY add default values to config.yml?

Discussion in 'Plugin Development' started by Etsijä, Aug 28, 2012.

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

    Etsijä

    I have a plugin which calles this function in onEnable():

    Code:
    public void processConfigFile() {
     
      FileConfiguration config = this.getConfig();
      final Map<String, Object> defParams = new HashMap<String, Object>();
           
      //_log.info("config = " + config.getKeys(true));
           
      // Create a default config.yml if one does not exist
           
      // These are the defaults
      defParams.put("general.magicaltool", 58);
      defParams.put("general.use_worldguard", "yes");
      defParams.put("general.use_logblock", "yes");
      defParams.put("general.debug", "yes");
      defParams.put("blocks.logs", "yes");
      defParams.put("blocks.stairs", "yes");
      defParams.put("blocks.pistons", "yes");
      defParams.put("blocks.chests", "yes");
      defParams.put("blocks.slabs", "yes");
      defParams.put("blocks.diodes", "yes");
      defParams.put("general.testparameter", 1);
       
      for (final Entry<String, Object> e : defParams.entrySet())
        if (!config.contains(e.getKey()))
          config.addDefault(e.getKey(), e.getValue());
     
      // Add defaults for any params that don't exist in (existing) config.yml <<<=== THIS DOESN'T WORK
      config.options().copyDefaults(true);
      this.saveDefaultConfig();
    }
    
    This is my config.yml:
    Code:
    general:
      magicaltool: 58
      use_worldguard: yes
      use_logblock: yes
      debug: yes
    blocks:
      logs: yes
      stairs: yes
      pistons: no
      chests: yes
      slabs: yes
      diodes: yes
    In essence, config.yml provided in my JAR is missing "general.testparameter" and should be added to ./datadir/config.yml. Alas, it is not - the config.yml in my data directory is always an exact copy of the config.yml inside my JAR.

    Could someone explain me how to really save the (missing) default values to my config.yml? I have debugged my code and the line "config.addDefault()..." does get executed when finding "general.testparameter", so that is not what's failing here, I'm sure I am just trying to use copyDefaults() and saveDefaultConfig() in a wrong way.
     
  2. Offline

    Theway2cool1

    @Etsijä
    Maybe instead of:
    Code:
    this.saveDefaultConfig();
    do:
    Code:
    saveConfig();
    Not entirely sure it will work, but it's worth a shot.
     
  3. Offline

    honestduane

    I'm still learning the API but in my most recent plugin I put this in a utility class named Setting:

    Code:
    import org.bukkit.configuration.file.FileConfiguration;
     
    public class Settings {
        private static void SetIfNoDefaultObject(FileConfiguration config, String path, Object value){
            if(config == null) return;
            if(path == null) return;
            if(value == null) return;
           
            if(!config.contains(path)){
                config.set(path, value);
            }
        }
    }
    
    And then used it as follows in the onEnable of the plugin like this:
    Code:
            FileConfiguration conf = this.getConfig();
            conf.options().copyDefaults(true);
     
            Settings.SetIfNoDefaultBool(conf,    "ConstantUsedInConfigFile", "value used for config option");
     
            this.saveConfig();
    
    This allows you to create a config file that uses sane defaults if it doesnt find anything or the person who is trying to use the plugin makes a mistakre or makes a typo in the file, without overwriting their changes by mistake. It also means they will not be able to complain (Not that this will stop them from doing so anyway!) that the plugin doesn't do the work of creating the file for them.
     
  4. Offline

    Etsijä

    honestduane: you nailed it, thank you! It really was a mistake from my part: I had also experimented with the "!config.contains() -> config.set()" idea, but failed to use copyDefaults() and saveConfig() properly (in proper order).

    Here's my code, which now works as intended:

    Code:
    public void processConfigFile() {
     
      final Map<String, Object> defParams = new HashMap<String, Object>();
      FileConfiguration config = this.getConfig();
      config.options().copyDefaults(true);
         
      // This is the default configuration
      defParams.put("general.magicaltool", 58);
      defParams.put("general.use_worldguard", "yes");
      defParams.put("general.use_logblock", "yes");
      defParams.put("general.debug", "yes");
      defParams.put("general.testparameter", 1);
      defParams.put("blocks.logs", "yes");
      defParams.put("blocks.stairs", "yes");
      defParams.put("blocks.pistons", "yes");
      defParams.put("blocks.chests", "yes");
      defParams.put("blocks.slabs", "yes");
      defParams.put("blocks.diodes", "yes");
     
      // If config does not include a default parameter, add it
      for (final Entry<String, Object> e : defParams.entrySet())
        if (!config.contains(e.getKey()))
          config.set(e.getKey(), e.getValue());
     
      // Save default values to config.yml in datadirectory
      this.saveConfig();
    }
     
  5. Offline

    Sagacious_Zed Bukkit Docs

    Instructions on how to do this properly is here http://wiki.bukkit.org/Introduction_to_the_New_Configuration
     
  6. Offline

    Etsijä

    I have read that article like 15 times, but to be honest, it really is not such a good one. It lacks a lot in terms of proper examples. The code in the end is anything but a proper demo, and particularly, the article is very vague when it comes to the differences of copyDefaults(), saveDefaultConfig(), and saveDonfig(). Moreover, it doesn't show a single example of how (and in what order) to properly use all of those methods. JavaDoc really doesn't help much, either.

    I think a lot of inexperienced Bukkit plugin developers could benefit of a good "HelloWorld" plugin, which doesn't do anything much, but introduces all the basic concepts of a plugin (enabling and disabling the plugin, handling diff. config files, commands, events, permissions, chat etc.). I am writing such myself, to try things out and document them to myself.
     
    Rexel likes this.
  7. Offline

    Sagacious_Zed Bukkit Docs

    There really is not a single correct order to call any of those methods. As for sample plugins, I have one on my github, it has two branches exploring different things.
     
  8. Offline

    Rexel

    Good I look forward to reading it.. you going to post link here??
     
  9. Offline

    Etsijä

    I will, once I get it done. In hopes someone else benefits from it. I myself have had lots of use of different tutorial threads posted here. I think that's what's good in open source.
     
  10. Offline

    honestduane

    Glad to help!
     
  11. Offline

    Etsijä

    https://github.com/Etsija/HelloWorld/blob/master/src/com/github/etsija/helloworld/HelloWorld.java

    Here's my HelloWorld plugin, which implements a little bit more intelligent file handling, multiple config files, default values processing etc. The code really is a copy-paste from here and there, so nothing new I think. Thanks go to DomovoiButler, who has written an especially good tutorial on multiple config file handling here:
    http://forums.bukkit.org/threads/bukkits-yaml-configuration-tutorial.42770/
    I just added default value processing to his code and generalised a bit, that's it. I think with my code, it will be pretty self-obvious to add more config files to plugin if needed.

    The code could use refactoring into different Java classes, but I just wouldn't be bothered :)
     
Thread Status:
Not open for further replies.

Share This Page