Different ways to save multiple config with comments

Discussion in 'Spigot Plugin Development' started by i998979, Oct 29, 2019.

  1. So recently I am dealing with multiple config with comments, but it seems that it is not that easy.
    I've tried different methods to get this done, but it failed of course.

    Here are some methods I've tried so far, also with the results.

    Declaration:
    Code (Text):
    private File file;
    private FileConfiguration fileConf;
    private String name = "config.yml";

    Code (Text):
            if (file == null) {
                file = new File(plugin.getDataFolder(), name);
            }
            if (!file.exists()) {
                plugin.saveResource(name, false);
            }
    file is not null and it exist, nothing happen and no changes or course

    Code (Text):
    plugin.saveResource(name, false);
    [14:21:19 WARN]: [FloatingOrb] Could not save config.yml to plugins\FloatingOrb\config.yml because config.yml already exists.
    config.yml already exist, unable to save and no changes made. Expected.

    Code (Text):
    plugin.saveResource(name, true);
    As far as I know, it overrides the old config with the new one, so no changes as expected.

    Code (Text):
            try {
                fileConf.save(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
    The most common file saving method I've seen, changes was made, but only headers were saved, that's how YamlConfiguration works, save header only

    So I would like to ask how can I save comments into different config after certain changes.

    What I want is:
    - If plugin folder config.yml not exist, copy from .jar. Otherwise load the existing one in plugin folder, # With COMMENTS #
    - Some changes like fileConf.set("FloatingOrb.Cancel_NoDamage_Sound", true);
    - Save everything including those was changed and of course the # COMMENTS # in any way. Eg Built-in method, write the file byte by byte

    Thank you so much. I know this is a very common issue, but I did really watched like 100+ threads related to this problem and even decompiled some famous plugin, but I am still unable to get a solution.
     
  2. The config.yml already exists, you just need save defaults or reload it, don't bother with anything else after all those methods are already written for you.
    There is a tutorial about multiple configs on the spigotMC wiki, check it out and your questions will probably be solved.
     
  3. Thanks for your reply, but I don't really know what you mean, would you please explain more?
     
  4. Code (Java):
    private static void copy(InputStream source, File dest) {
           try {
               try (InputStream input = source; OutputStream output = new FileOutputStream(dest)) {
                   byte[] buf = new byte[1024];
                   int bytesRead;
                   while ((bytesRead = input.read(buf)) > 0) {
                       output.write(buf, 0, bytesRead);
                   }
                   input.close();
                   output.close();
               }
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
    Usage: copy(plugin.getResource(file), destination)

    This method will let you copy a resource file while preserving its contents
     
    • Like Like x 1
  5. I don't know if I used the method correctly, but it is not saving anything.
    Code (Text):
    fileConf.set("FloatingOrb.Cancel_NoDamage_Sound", cancel);
    copy(plugin.getResource(name), file);
    The config.yml was modified but the contents are the same.
     
  6. I read this tutorial already. The tutorial already said that
    But what I want to do is to save comments in the config.yml, which this tutorial can't achieve.
     
  7. You got me confused, you want to write comments via code or write the comments directly to .yml file and load(the .yml file) it when the plugin starts?

    Edit: wording.
     
  8. From
    Code (Text):
    # Header
    FloatingOrb:
      Enabled: true
      Language: en_US
      # ProtocolLib required <----- comments at the middle of the config.yml
      Cancel_NoDamage_Sound: false
    Via code
    Code (Text):
    fileConf.set("FloatingOrb.Cancel_NoDamage_Sound", true);
    Into
    Code (Text):
    # Header
    FloatingOrb:
      Enabled: true
      Language: en_US
      # ProtocolLib required <----- still exist even some settings were changed
      Cancel_NoDamage_Sound: true
    What I want is the comment remains after certain settings were changed.
    But I can only make the config become this
    Code (Text):
    # Header
    FloatingOrb:
      Enabled: true
      Language: en_US   ↙The comment is gone
      Cancel_NoDamage_Sound: true
    Does it sound clearer?
     
  9. Why that complicated?
    Code (Java):
    Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
     
    • Informative Informative x 1
  10. I see, read the last post from this thread: thread
     
  11. I have personally tried many methods and I was in this exact situation. To save you some time, here are your options:
    • Use the current YAML parser with spigot, and have no comments
    • Write your own YAML parser that supports comments
    • Use a different configuration system that supports comments, like TOML (TOMLJ)
    Those above are your best options to achieve what you are going for. Those professional plugins don't use SnakeYAML, they use their own implementation of the system. I personally use TOML now, and it works great.
     
    #12 yakovliam, Oct 29, 2019
    Last edited: Oct 29, 2019
  12. Saying that we haven't read the thread is kinda rude, sorry for misunderstanding what he meant and when I understood it wasn't what he/she meant, I asked for clarification and linking to a thread which explained why that happened and what he needs to do if he wants to fix it.
     
  13. Didn't mean to sound rude; I just wanted to stop the constant flow of answers that didn't fit with the question. It's alright that you didn't understand what was meant in the original post. I just happened to because I have been in this exact situation.
     
  14. I have a resource that is pretty much exactly what your looking for. It will add all your comments and you can also use it to update your config if you so happen to add more configuration option for your plugin. You can find it on GitHub here. Sort of plugging, but I think it can help you.
     
  15. Thanks for your reply, the options you've provided really saves my time. But I would like to ask is there any tutorial in creating own YAML parser that the professional plugin does?

    Thanks for reply and I'll try to use that :D
     
  16. Code (Text):
    fileConf.set("FloatingOrb.Cancel_NoDamage_Sound", cancel);
    try {
                  ConfigUpdater.update(plugin, "config.yml", file, new ArrayList<>());
                } catch (IOException e) {
                  e.printStackTrace();
                }
    }
    This is what I wrote in the code. It doesn't seem to work. I don't have sections to ignore so I simply put an empty ArrayList since putting null will leads to an error.
    And the modification made by
    is not saving, the file just get modified and the data is not changing.
     
  17. I am not sure what you mean. config.set("FloatingOrbCancel_NoDamage_Sound", cancel) will save to the cached config, but you need to save the config using config#save or JavaPlugin#saveConfig to actually write it to storage. If you want your comments to persist after saving the config you need to call the update method after saving the config.
     
  18. OMG it really works! I thought your method saves the config for me, you just reminded me that.
    This is my code if anyone interested.
    Code (Text):
            fileConf.set("FloatingOrb.Cancel_NoDamage_Sound", cancel); // cancel: true/false
            try {
                fileConf.save(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
           
            try {
                ConfigUpdater.update(plugin, "config.yml", file, new ArrayList < > ());
            } catch (IOException e) {
                e.printStackTrace();
            }
    But I still wanted to ask how can I make a custom Yaml parser / your ConfigUpdater, everyone wants customized version :D
    Also, I would like to know how the normal bukkit/spigot config system works and how you save the comment with your code.

    But whatever, thank you so much, you saved my life.