[Guide] Creating Custom Configs

Discussion in 'Spigot Discussion' started by GrimmChild, Aug 10, 2018.

?

Was this helpful?

  1. Yeah!

    43.8%
  2. Meh...

    18.8%
  3. Confusing

    25.0%
  4. Horrible!

    12.5%
  1. So earlier on when I was trying to learn my way around the Spigot API, something I really wanted to do was label stuff in my config.yml with comments. However, there wasn't really a method to do that using the normal default config.

    After a lot of snooping around, I finally found some tutorials on how to make custom configuration files, however they were still too complicated for me to understand. Only after a lot of trial and error did I find out how, and even then, it was very flawed. That's why I'm going to try and guide people through creating customized configs within the project itself.



    The first step is creating the configuration file in your workplace. In order for the plugin to find the file, you'll want to keep it in a Resources Root directory. Typically, this is how I set my project up:
    [​IMG]
    Note: I am using IntelliJ along with the Minecraft Development plugin for IntelliJ, so stuff may be slightly different.

    In my resources directory, along with the plugin.yml, I would create a config / yml file. The file can be called anything, I just called it config.yml for simplicity. If you are having trouble creating a resources folder, do the following:

    IntelliJ: Create Directory -> Right Click Directory -> Mark Directory As -> Resources Root
    Eclipse: Install IntelliJ... or do Select project, right-click -> Build path -> Use as resource folder.
    (Thanks https://stackoverflow.com/a/26519047/8954641 for Eclipse solution)

    Now just put anything you want in your config, I just put in
    Code (YAML):
    # Hey! This is a comment!

    config
    :
      giant
    :
     - fe
      - fi
      - fo
      - fum
    for a random example



    Alright, now onto the fun stuff!

    There are two ways I know how to handle custom configs. Java.io, and Java.nio. Both ways are fine, and you may find it easier using Java.io since it's used a bit more often than Java.nio from what I've seen. This is where you can get a bunch of different variations depending on your style / plugin.

    This can change depending on what you like to do, the complexity, and if you have multiple configuration files. If you have multiple configuration files, you may want to take a look at the following two classes:

    Using Java.io:
    Code (Java):
    public abstract class temp {

        // The .yml file itself
        private File file;

        // The data folder directory
        private File dir;

        // The configuration field for 'reading' the file
        private YamlConfiguration yaml;

        temp(JavaPlugin plugin, String name) {

            dir = plugin.getDataFolder();

            // I generally ignore the boolean result
            if(!dir.exists()) {
                dir.mkdirs();
            }

            // Creates a file in the data folder directory called 'name'.
            file = new File(dir, name);

            // If it is not located in here, find the file in the resources
            // directory in the project and save it to the data directory.
            if(!file.exists()) {
                plugin.saveResource(name, false);
            }

            // Making a new configuration
            yaml = new YamlConfiguration();

            // Loading the file's data into the configuration field
            try {
                yaml.load(file);
            } catch (IOException | InvalidConfigurationException e) {
                e.printStackTrace();
            }
        }

        // Saves the configuration data
        public void save() {
            try {
                yaml.save(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // Basic getter for retrieving the configuration data
        public YamlConfiguration getYaml() {
            return yaml;
        }
    }

    Using Java.nio:
    Code (Java):
    public abstract class ConfigurationFile {

        // Path to the config file
        private Path file;

        // Path to the data directory
        private Path dir;

        // The configuration for the config
        private YamlConfiguration yaml;

        public ConfigurationFile(JavaPlugin plugin, String name) {

            // Sets the directories location
            dir = plugin.getDataFolder().toPath();

            // If it doesn't exist, create it, and replace the value
            // with the newly created directory
            if(!Files.exists(dir)) {
                try {
                    dir = Files.createDirectory(dir);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            // Saves the file from the resources directory to the data directory
            plugin.saveResource(name, false);

            // Creates the file in the data directory
            file = dir.resolve(name);

            // New configuration
            yaml = new YamlConfiguration();

            // Loads the file data into the configuration
            try {
                yaml.load(file.toString());
            } catch (IOException | InvalidConfigurationException e) {
                e.printStackTrace();
            }
        }

        // Saves the configuration data
        public void save() {
            try {
                yaml.save(file.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // Simple Getter
        public YamlConfiguration getYaml() {
            return yaml;
        }

        // Gets the path to the data directory
        public Path getDataPath() {
            return dir;
        }
    }
    Some quick answers to any possible questions from these previous classes:

    What is abstract? Long story short: Prevents you from creating a new instance / object of it, but allows different classes to extend that class. Useful to keep certain methods apart when having multiple classes.

    Which is better? Well, I'm no expert on that really, it'll all depend on which you like more, or if someone more knowledgeable replies which is better in this case. Personally, I like Java.nio because it's storing the path to the file instead of the file itself.



    Now, onto how you would get the configuration data:

    Code (Java):
    public class Config extends ConfigurationFile {

        // super(); means it'll plug those values into the constructor for the extended class
        public Config(JavaPlugin plugin, String name) {
            super(plugin, name);
        }

        // Gets the list of strings in the config file, in the path "config.giant"
        public List<String> getGiantSpeech() {
            return this.getYaml().getStringList("config.giant");
        }
    }
    This will return the List of Strings, [fe, fi, fo, fum].



    If you just had a singular config and just want to make one class to handle it all, then you can remove the abstract from the class. Then, instead of creating a new Config class extending the previously "abstract" class, or ConfigurationFile, in the class (ConfigurationFile) itself, create the methods.

    Just add
    Code (Java):
        // Gets the list of strings in the config file, in the path "config.giant"
        public List<String> getGiantSpeech() {
            return this.getYaml().getStringList("config.giant");
        }
    to the bottom of your new configuration file and you'll get something like this: (Java.io version)

    Code (Java):
    public class Config {

        // The .yml file itself
        private File file;

        // The data folder directory
        private File dir;

        // The configuration field for 'reading' the file
        private YamlConfiguration yaml;

        temp(JavaPlugin plugin, String name) {

            dir = plugin.getDataFolder();

            // I generally ignore the boolean result
            if(!dir.exists()) {
                dir.mkdirs();
            }

            // Creates a file in the data folder directory called 'name'.
            file = new File(dir, name);

            // If it is not located in here, find the file in the resources
            // directory in the project and save it to the data directory.
            if(!file.exists()) {
                plugin.saveResource(name, false);
            }

            // Making a new configuration
            yaml = new YamlConfiguration();

            // Loading the file's data into the configuration field
            try {
                yaml.load(file);
            } catch (IOException | InvalidConfigurationException e) {
                e.printStackTrace();
            }
        }

        // Saves the configuration data
        public void save() {
            try {
                yaml.save(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // Basic getter for retrieving the configuration data
        public YamlConfiguration getYaml() {
            return yaml;
        }

        // Gets the list of strings in the config file, in the path "config.giant"
        public List<String> getGiantSpeech() {
            return yaml.getStringList("config.giant");
        }
    }


    If anything is wrong / uninformative, please tell me as soon as you spot it so I can correct the mistake. If you have any questions, feel free to ask them,

    good luck!
     
  2. You're still using bukkit's YamlConfiguration? So where is the difference to the common way (e.g. #saveDefaultConfig)?
    It's the same. I'm Pretty sure comments will not be supported except in the first line with your solution.

    So i guess you did not achieve, what you wanted to - use comments anywhere (just try it at the end - it will disappear after the first time you call YamlConfiguration#save, or #set... i'm not sure). However there is no advantage to the default system.

    Do you know about the bukkit wiki? All you need to know is written there since ages: https://bukkit.gamepedia.com/Configuration_API_Reference#Using_an_alternate_configuration_file.

    After all i can't see why this would help anyone. I'm even worrying, it only will confuse beginners.

    At the end i want to Mention there are already many threads about comments on this forum, you don't need google - use the forums search.
    In some of them i participated, e.g: