[Tutorial/Beginner] Making configs

Discussion in 'Resources' started by theguynextdoor, Dec 30, 2011.

  1. Offline

    theguynextdoor

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    When making a plugin, alot of server owners will want things to be configurable, because they like to have as much control as possible (who doesnt?). I know there are other config tutorials out there, but i feel config is something i can do in bukkit without a massive amount of trouble

    Note: The examples use the old event system, but the way you use the config has not changed

    For a more detailed tutorial on using configs in different classes please go to my other tutorial: : http://forums.bukkit.org/threads/config-from-another-class.61899/

    Right, so it's been a while since i have done a tutorial, and i have been wanting to update and improve my config tutorial. So here is it updated and laid out a bit better (i hope).


    Right, so i have made a very simple main class for a plugin here:
    Code:
    package tk.theguynextdoor.configtutorial;
     
    import org.bukkit.plugin.java.JavaPlugin;
     
    public class ConfigTutorial extends JavaPlugin {
     
        @Override
        public void onEnable() {
     
        }
     
    }
    

    Now in our onEnable we shall put the following code:

    Code:
    package tk.theguynextdoor.configtutorial;
     
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
     
    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.plugin.java.JavaPlugin;
     
    public class ConfigTutorial extends JavaPlugin {
     
        String[] listOne = { "one", "two", "three", "four" };
        List<String> listTwo = new ArrayList<String>();
     
        @Override
        public void onEnable() {
            listTwo.add("one");
            listTwo.add("two");
            listTwo.add("three");
            listTwo.add("four");
     
            FileConfiguration config = getConfig();
     
            config.addDefault("Example.String", "This is a string");
            config.addDefault("Example.Int", 1);
            config.addDefault("Example.Boolean", true);
            config.addDefault("Example.List.One", Arrays.asList(listOne));
     
            config.addDefault("Example.List.Two", listTwo);
     
            config.options().copyDefaults(true);
            saveConfig();
        }
     
    }

    This will create a config which looks like this:

    Code:
    Example:
      String: This is a string
      Int: 1
      Boolean: true
      List:
        One:
        - one
        - two
        - three
        - four
        Two:
        - one
        - two
        - three
        - four

    Now of course you can replace any of these values, for example you could change the array of strings to an array of lists:

    Code:
    int[] listOne = {1, 2, 3, 4 };

    And it would look like the list originally did, only this time it would be the numbers.


    -------------------------------------------------------------------------------------------------------


    Now i want to break it down a bit.
    The way we get our config is through use of the method 'getConfig()'. Now the reason we can use this method is because we are in our main class which extends JavaPlugin, and JavaPlugin has the getConfig method in it so we can just use that in this class.

    So what we did with the getConfig() method is that we assigned it to a variable, this variable was of the type FileConfiguration and we called it config. So now when ever we type config. we should get a nice list of all the different options we can use.

    The method we used here is the 'addDefault()' method which takes 2 parameters, those being the path in the config and the next being the value. The way the path works is that it is in the form of a string, so when we define it we use "", and whenever you put a full stop in that (.) then it considers that as a new 'section' in a sense. That is how we got the indentations in the examples. This is very handy for making the config organised and readable. It also helps you as a programmer because you can organise the config to a way which is neat and easy for you to understand as well.

    Now after we defined all of our defaults we used 2 more methods. These were 'config.options().copyDefaults(true)' and 'saveConfig()'. Now what the copy defaults method does is pretty much as it says in that when the config is made it copies all of the defaults you defined above and writes them to the file and then after that we used the saveConfig method to simple save it.

    That is the basis of our config made up. The next stage is working out how to get a value from our config



    Getting values

    Now you have made some values in your config, you will want to be able to access them, doing so is very simple, i am probably not the best example for stuff, but when i make plugins, i have a tendency to make all my listeners inner classes. This does make using the config easier for me.

    Now the main way to get your config items.
    Code:java
    1. config.getString("Example.String");
    2. config.getInt("Example.Int");
    3. config.getBoolean("Example.Boolean");
    4. config.getList("example.list.path");

    Now notice how you only have to define the path, that is because you have already defined the value in your defaults at the start.

    An example use for these could be
    String:
    Code:java
    1. @Override
    2. public void onEnable() {
    3.  
    4. FileConfiguration config = this.getConfig();
    5. config.addDefault("Example.String", "Yo i am a string" );
    6.  
    7. PluginManager pm = getServer().getPluginManager();
    8. pm.registerEvent(Type.PLAYER_JOIN, new PlayerListener() {
    9.  
    10. @Override
    11. public void onPlayerJoin(PlayerJoinEvent event) {
    12. event.getPlayer().sendMessage(config.getString("Example.String"));
    13. }
    14. }, Priority.Normal, this);
    15.  
    16. config.options().copyDefaults(true);
    17. saveConfig();
    18. }


    Int:

    Code:java
    1. @Override
    2. public void onEnable() {
    3.  
    4. FileConfiguration config = this.getConfig();
    5.  
    6. config.options().header("Yo this is a header test");
    7. config.addDefault("Example.Player.Int", 5);
    8. config.addDefault("Example.Mob.Int", 4);
    9.  
    10. PluginManager pm = getServer().getPluginManager();
    11. pm.registerEvent(Event.Type.ENTITY_DAMAGE, new EntityListener() {
    12. int damage;
    13.  
    14. public void onEntityDamage(EntityDamageEvent event) {
    15.  
    16. if (event instanceof EntityDamageByEntityEvent) {
    17. Entity attacker = ((EntityDamageByEntityEvent) event).getDamager();
    18.  
    19. if (attacker instanceof Snowball) {
    20.  
    21. if (((Snowball) attacker).getShooter() instanceof Snowman && config.getBoolean("Snowball.SnowmanDamage") && !(attacker instanceof Player)) {
    22. damage = config.getInt("Snowball.SnowmanDamageInt");
    23. event.setDamage(damage);
    24. }
    25.  
    26. if (event.getEntity() instanceof Player) {
    27. damage = config.getInt("Snowball.PlayerDamageInt");
    28. }
    29.  
    30. else if (event.getEntity() instanceof LivingEntity && !(event.getEntity() instanceof Player)) {
    31. damage = config.getInt("Snowball.MobDamageInt");
    32. } else {
    33. return;
    34. }
    35.  
    36. event.setDamage(damage);
    37. }
    38. }


    Boolean:
    Code:java
    1. @Override
    2. public void onEnable() {
    3.  
    4. FileConfiguration config = this.getConfig();
    5. config.addDefault("Example.String", "Yo i am a string" );
    6. config.addDefault("Example.Boolean", true );
    7.  
    8. PluginManager pm = getServer().getPluginManager();
    9. pm.registerEvent(Type.PLAYER_JOIN, new PlayerListener() {
    10.  
    11. @Override
    12. public void onPlayerJoin(PlayerJoinEvent event) {
    13. if (config.getBoolean("Example.Boolean")) {
    14. event.getPlayer().sendMessage(config.getString("Example.String"));
    15. }
    16. }
    17. }, Priority.Normal, this);
    18.  
    19. config.options().copyDefaults(true);
    20. saveConfig();
    21. }


    Note the difference, the string example would show every player that logged on that message. The boolean example will only show the message if it is set to true.

    List:

    Code:java
    1. String[] rules = { "Rule1", "Rule2", "Rule3" };
    2.  
    3. @Override
    4. public void onEnable() {
    5. FileConfiguration config = this.getConfig();
    6. config.addDefault("Example.list.path", Arrays.asList(rules));
    7.  
    8. config.options().copyDefaults(true);
    9. saveConfig();
    10. }
    11.  
    12. public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    13. if (label.equalsIgnoreCase("rules")) {
    14. List<String> rules = getConfig().getList(" Example.list.path ");
    15. for (String s : rules) {
    16. sender.sendMessage(s);
    17. }
    18. return true;
    19. }
    20. return false;
    21. }



    Setting values:

    Now in your plugin you may want to cater for those lazy admins who want to change values in game, and tbh i am one of them. I dont want to have to go over to the config and manually change things, commands are the way to go. And so relating to our motd thing we have going, to change the motd while ingame, you do.
    Code:java
    1. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    2. if (cmd.getName().toLowerCase().equals("setmotd")) {
    3. for (Player player : getServer().getOnlinePlayers()) {
    4.  
    5. StringBuilder sb = new StringBuilder();
    6. for (int i = 0; i < args.length; i++) {
    7. if (i != 0)
    8. sb.append(' ');
    9. sb.append(args);
    10. }
    11. String motd = sb.toString();
    12. config.set("Default.motd", motd.replaceAll("(&([a-f0-9]))", "\u00A7$2"));
    13. saveConfig();
    14. return true;
    15. } else {
    16. sender.sendMessage(ChatColor.RED + "[ChatNextDoor] " + ChatColor.YELLOW + "You don't have permission");
    17. }
    18. }
    19. return false;
    20. }


    If you change a value, don't forget to use saveConfig(), so it actually saves the config.

    Getting values from config, while in a separate class.

    That was a confusing title to write. None the less the aim of this section is to get a value from your config in your onEnable method while you are in a separate class.

    Now i am going to assume you class is a listener of some sort and you have the lovely constructor at the start so your listener looks like this.
    Code:java
    1. public class BulletinPlayerListener implements Listener {
    2. BulletinNextDoor plugin;
    3.  
    4. public BulletinPlayerListener(BulletinNextDoor instance) {
    5. plugin = instance;
    6. }

    Note this is implementing listener due to the new event system in place. Now to make this apply to your main class you need to replace accordingly, to help you i will set it up as following, <main class> will be your main class and <listener> will be the name of your listener.
    Code:java
    1. public class <listener> implements Listener {
    2. <main class> plugin;
    3.  
    4. public <listener>(<main class> instance) {
    5. plugin = instance;
    6. }

    Ok, so now we got that variable, we can simply refer to it when we want to access something from our main class, in this case that will be our config.

    The way we get a value from another class in our listener we put the lines as following;
    Code:java
    1. plugin.config.getString("Path.String");
    2. plugin.config.getInt("Path.Int");
    3. plugin.config.getBoolean("Path.Boolean");
    4. plugin.config.getList("Path.List");


    An example use of this may be.
    Code:java
    1. public class BulletinPlayerListener implements Listener {
    2. BulletinNextDoor plugin;
    3.  
    4. public BulletinPlayerListener(BulletinNextDoor instance) {
    5. plugin = instance;
    6. }
    7.  
    8. @EventHandler
    9. public void onPlayerChat(PlayerChatEvent event) {
    10. String msg = event.getMessage();
    11.  
    12. if (msg.startsWith(">")) {
    13. event.setMessage(ChatColor.getByCode(plugin.config.getInt("Example.>")) + msg);
    14. }
    15. }


    Final example of a main class.

    Code:java
    1. package me.theguynextdoor.snowballnextdoor;
    2.  
    3. import java.util.logging.Logger;
    4.  
    5. import me.theguynextdoor.snowballnextdoor.commands.CritCommand;
    6. import me.theguynextdoor.snowballnextdoor.commands.HeadShotCommand;
    7. import me.theguynextdoor.snowballnextdoor.commands.IceCommand;
    8. import me.theguynextdoor.snowballnextdoor.commands.MissCommand;
    9. import me.theguynextdoor.snowballnextdoor.commands.MobDamageValue;
    10. import me.theguynextdoor.snowballnextdoor.commands.PlayerDamageValue;
    11. import me.theguynextdoor.snowballnextdoor.commands.SnowTilePlaceToggle;
    12. import me.theguynextdoor.snowballnextdoor.commands.SnowmanDamage;
    13. import me.theguynextdoor.snowballnextdoor.listeners.SnowballBlockListener;
    14. import me.theguynextdoor.snowballnextdoor.listeners.SnowballEntityListener;
    15. import me.theguynextdoor.snowballnextdoor.listeners.SnowballPlayerListener;
    16.  
    17. import org.bukkit.Bukkit;
    18. import org.bukkit.configuration.file.FileConfiguration;
    19. import org.bukkit.plugin.PluginManager;
    20. import org.bukkit.plugin.java.JavaPlugin;
    21.  
    22. public class SnowBallNextDoor extends JavaPlugin {
    23.  
    24. private final Logger log = Logger.getLogger("Minecraft");
    25. private final SnowballEntityListener entityListener = new SnowballEntityListener(this);
    26. private final SnowballPlayerListener playerListener = new SnowballPlayerListener(this);
    27. private final SnowballBlockListener blockListener = new SnowballBlockListener(this);
    28.  
    29. @Override
    30. public void onDisable() {
    31. log.info(this.getDescription().getName() + " has been disabled");
    32. }
    33.  
    34. @Override
    35. public void onEnable() {
    36.  
    37. FileConfiguration config = this.getConfig();
    38.  
    39. config.options().header("The Server.PvP node: Set to true if PvP is enabled, and false if PvP is diabled.");
    40.  
    41. config.addDefault("Server.PvP", true);
    42.  
    43. config.addDefault("Toggle.Damage.PlayerDamage", true);
    44. config.addDefault("Toggle.Damage.MobDamage", true);
    45. config.addDefault("Toggle.Damage.SnowmanDamage", true);
    46.  
    47. config.addDefault("Toggle.Snowball.PlaceOnRightClick", true);
    48. config.addDefault("Toggle.Snowball.SnowTileStacking", true);
    49. config.addDefault("Toggle.Snowball.PutEntityFiresOut", true);
    50. config.addDefault("Toggle.Snowball.WaterToIce", true);
    51.  
    52. config.addDefault("Value.PlayerDamage", 2);
    53. config.addDefault("Value.MobDamage", 2);
    54. config.addDefault("Value.SnowmanDamage", 2);
    55.  
    56. config.addDefault("Crit.Chance", true);
    57. config.addDefault("Crit.DamageExtra", true);
    58. config.addDefault("Crit.Toggle.Message", true);
    59.  
    60. config.addDefault("Miss.Chance", true);
    61. config.addDefault("Miss.Toggle.Message", true);
    62.  
    63. config.addDefault("Headshot.Toggle.HeadshotDamage", true);
    64. config.addDefault("Headshot.Toggle.HeadshotMessage", false);
    65. config.addDefault("Headshot.Value.HeadshotExtraDamageDealt", 1);
    66.  
    67. config.addDefault("Debug.Damage.Messages", false);
    68. config.addDefault("Debug.nullMessage", false);
    69.  
    70. config.options().copyDefaults(true);
    71. saveConfig();
    72.  
    73. PluginManager pm = Bukkit.getServer().getPluginManager();
    74.  
    75. pm.registerEvents(playerListener, this);
    76. pm.registerEvents(blockListener, this);
    77. pm.registerEvents(entityListener, this);
    78.  
    79. getCommand("splayer").setExecutor(new PlayerDamageValue(this));
    80. getCommand("mob").setExecutor(new MobDamageValue(this));
    81. getCommand("snowman").setExecutor(new SnowmanDamage(this));
    82. getCommand("snowtile").setExecutor(new SnowTilePlaceToggle(this));
    83. getCommand("miss").setExecutor(new MissCommand(this));
    84. getCommand("crit").setExecutor(new CritCommand(this));
    85. getCommand("headshot").setExecutor(new HeadShotCommand(this));
    86. getCommand("snowice").setExecutor(new IceCommand(this));
    87.  
    88. log.info(this.getDescription().getName() + " v" + getDescription().getVersion() + " has been enabled");
    89. }
    90. }




    Thank you for reading, if i missed something do say, and i will add it to tutorial.

    This post has been edited 12 times. It was last edited by theguynextdoor May 19, 2012.
    Woobie, Neodork, Milkywayz and 10 others like this.
  2. Offline

    Jaker232

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Finally, an updated efficient configuration tutorial. This is my new method. Thanks, @theguynextdoor !
    TopGear93 and theguynextdoor like this.
  3. Offline

    Supertt007

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    What are the differences between FileConfigurations and Configurations? Which method is more efficient or they are just the same?
  4. Offline

    TheFieldZy

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    If you are specifically talking about the classes, Configurations is an interface that FileConfigurations implements. Meaning alone, the Configurations class isn't much. If you are talking about the difference between FileConfigurations and YamlConfigurations, FileConfigurations makes a generic config.yml while YamlConfigurations opens more doors for configs like users.yml or <different_file>.yml
  5. Offline

    Supertt007

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    ok, i m currently using bukkit's Configuration class to store my datas like a flatfile. Any suggestions on that?
  6. Offline

    TheFieldZy

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Well, none of my plugins use datastorages, even my private ones. I am making a plugin that will use one, but datastorage is last on my list cause it scares me. I'd recommend if you use anything for storage within bukkit, make a new YamlConfiguration with a different file name. The FileConfiguration class makes it config.yml by default, so that could easily confuse people. But for actual datastorage, if it is small, flatfile works well, large datastorages MySQL or SQLite are good options.
  7. Offline

    Supertt007

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    well actually, i am currently using
    PHP:
    new Configuration(new File(plugin.getDataFolder(), "data.yml"));
    which will make a file named data.yml under plugin data folder :). The problem i m worrying about is that everytime i fetch some data from the file, i have to load the entire file. I have seen people doing cache or something that load all datas on plugin start and you can easily fetch data in a hashmap. Which method do you prefer?
  8. Offline

    edocsyl

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Is there a way to add Comments ?
  9. Offline

    theguynextdoor

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Not to my knowledge, i think the only way was to make a config.yml and add it to your plugin when you export it or something, and it would have comments, but the comments would get deleted when the config is saved. So until someone has a solution i don't think there are any easy ways to add comments.
  10. Offline

    edocsyl

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
  11. Offline

    MrMag518

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    What about the lists? like: Boolean lists, String lists, Key lists, Byte lists etc. Would be nice to implement them here :)
  12. Offline

    Sagacious_Zed Bukkit Docs

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Since you had to ask this question, then the tutorial did not really do a good job of teach you how to use the API. It excels because it gives you snippets to follow and examples. Yes, the tutorial shows you what to do in great detail, but here you must instead think how to use certain methods to achieve what you want.

    The instructions for any given List would be like the list example but with the corresponding value in its place.

    This post has been edited 1 time. It was last edited by Sagacious_Zed Jan 14, 2012.
  13. Offline

    MrMag518

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I only said it would be nice to implement them, but whatever.
  14. Offline

    theguynextdoor

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Updated: getting values from config from another class (i dont know how to say it)

    pretty much getting values from your config which is in your main class while you are in your listener class.

    Please comment, for i feel that this may need some more explaining. Which i am glad to do btw on any part of the tutorial.

    This post has been edited 1 time. It was last edited by theguynextdoor Jan 20, 2012.
  15. Offline

    Darkhand81

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I'm glad you added the section about referencing config variables from another class, that's the part I've had trouble with. :)

    I haven't switched over to the new event system yet, is there anything hugely different when doing so on the old system? I can't seem to get my listener class to see it yet (field not visible).
  16. Offline

    theguynextdoor

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Making the plugin variable from another class with the old event system is the same really. I shall show you an example of it with old system.

    This would be my main class.
    Code:java
    1. public class SnowBallNextDoor extends JavaPlugin {
    2.  
    3. private final Logger log = Logger.getLogger("Minecraft");
    4. private final SnowballEntityListener entityListener = new SnowballEntityListener(this);
    5. private final SnowballPlayerListener playerListener = new SnowballPlayerListener(this);
    6. private final SnowballBlockListener blockListener = new SnowballBlockListener(this);
    7.  
    8. @Override
    9. public void onDisable() {
    10. log.info(this.getDescription().getName() + " has been disabled");
    11. }
    12.  
    13. @Override
    14. public void onEnable() {
    15. log.info(this.getDescription().getName() + " v" + getDescription().getVersion() + " has been enabled");
    16.  
    17. PluginManager pm = Bukkit.getServer().getPluginManager();
    18. pm.registerEvent(Type.ENTITY_DAMAGE, entityListener, Priority.Normal, this);
    19. pm.registerEvent(Type.PROJECTILE_HIT, entityListener, Priority.Normal, this);
    20. pm.registerEvent(Type.PLAYER_INTERACT, playerListener, Priority.Normal, this);
    21. pm.registerEvent(Type.BLOCK_BREAK, blockListener, Priority.Normal, this);


    And this would be my block listener for example.
    Code:java
    1. public class SnowballBlockListener extends BlockListener {
    2. SnowBallNextDoor plugin;
    3.  
    4. public SnowballBlockListener(SnowBallNextDoor instance) {
    5. plugin = instance;
    6. }
    7.  
    8. @Override
    9. public void onBlockBreak(BlockBreakEvent e) {
    10.  
    11. bla bla bla bla


    Note that in your main class you need
    Code:java
    1. private final SnowballBlockListener blockListener = new SnowballBlockListener(this);

    With the main part being the 'this'

    This post has been edited 1 time. It was last edited by theguynextdoor Jan 22, 2012.
  17. Offline

    Dark_Balor

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    You can't add comments, but you can set the header of the file (a major comment for all the file) like that :

    Code:java
    1.  
    2. getConf().options().header("Example on How to set an header");
    3.  

    Every time your configuration is saved, the header is rewrite first :)

    Moreover I created a new System to use and configure easily the config file, using a Enum :
    1) the ConfigEnum :
    Every item of the enum have 3 parts :
    1) the "path" in the configuration file
    2) the default value of that path
    3) a description of what for the path exists.

    And of course like every Enum the "name" of the item.
    Code:java
    1.  
    2. /************************************************************************
    3.  * This file is part of WarpSign.
    4.  *
    5.  * WarpSign is free software: you can redistribute it and/or modify
    6.  * it under the terms of the GNU General Public License as published by
    7.  * the Free Software Foundation, either version 3 of the License, or
    8.  * (at your option) any later version.
    9.  *
    10.  * WarpSign is distributed in the hope that it will be useful,
    11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13.  * GNU General Public License for more details.
    14.  *
    15.  * You should have received a copy of the GNU General Public License
    16.  * along with WarpSign. If not, see <[url]http://www.gnu.org/licenses/>[/url].
    17.  ************************************************************************/
    18. /**
    19.  * @author Balor (aka Antoine Aflalo)
    20.  *
    21.  */
    22. package be.Balor.WarpSign;
    23.  
    24. import java.util.LinkedHashMap;
    25. import java.util.Map;
    26.  
    27. import org.bukkit.configuration.ConfigurationSection;
    28.  
    29. public enum ConfigEnum {
    30. KEYWORD("warpKeyWord", "[ACWarp]", "set the keyword used to recognise a WarpSign.\n "
    31. + "BE CAREFULL if you change it, older WarpSign will be not working."),
    32. AUTOCOMPLETE(
    33. "autoComplete", true,
    34. "when typing the name of a world of a warp, if set to true, will autocomplete the Sign."),
    35. WORLDNF(
    36. "worldNotFound", "This World doesn't exists : ",
    37. "Message used when using the autoComplete feature and the World couldn't be found."),
    38. WARPNF(
    39. "warpNotFound", "This Warp doesn't exists : ",
    40. "Message used when using the autoComplete feature and the Warp couldn't be found."),
    41. COLOR(
    42. "useColor", true,
    43. "When set to true, will automatically color the World and Warp name on the sign using the color defined below.");
    44.  
    45. private final String confVal;
    46. private final Object defaultVal;
    47. private final String description;
    48. private static ConfigurationSection config;
    49.  
    50. /**
    51.   * @param confVal
    52.   * @param defaultVal
    53.   * @param description
    54.   */
    55. private ConfigEnum(String confVal, Object defaultVal, String description) {
    56. this.confVal = confVal;
    57. this.defaultVal = defaultVal;
    58. this.description = description;
    59. }
    60.  
    61. public String getString() {
    62. return config.getString(confVal);
    63. }
    64.  
    65. public int getInt() {
    66. return config.getInt(confVal);
    67. }
    68.  
    69. public double getDouble() {
    70. return config.getDouble(confVal);
    71. }
    72.  
    73. public boolean getBoolean() {
    74. return config.getBoolean(confVal);
    75. }
    76.  
    77. public long getLong() {
    78. return config.getLong(confVal);
    79. }
    80. /**
    81.   * @return the defaultvalues
    82.   */
    83. public static Map<String, Object> getDefaultvalues() {
    84. Map<String, Object> values = new LinkedHashMap<String, Object>();
    85. for (ConfigEnum ce : values())
    86. values.put(ce.confVal, ce.defaultVal);
    87. return values;
    88. }
    89.  
    90. public static String getHeader() {
    91. StringBuffer buffer = new StringBuffer();
    92. for (ConfigEnum ce : values())
    93. buffer.append(ce.confVal).append("\t:\t").append(ce.description).append(" (Default : ")
    94. .append(ce.defaultVal).append(')').append('\n');
    95. return buffer.toString();
    96. }
    97. /**
    98.   * @param config the config to set
    99.   */
    100. public static void setConfig(ConfigurationSection config) {
    101. ConfigEnum.config = config;
    102. }
    103. }
    104.  
    105.  

    2) How to use it on the onEnable event of your Plugin :
    Code:java
    1.  
    2. public void onEnable() {
    3. FileConfiguration conf = getConfig();
    4. ConfigEnum.setConfig(conf);
    5. conf.addDefaults(ConfigEnum.getDefaultvalues());
    6. conf.options().header(
    7. "This is the configuration file of WarpSign\n" + ConfigEnum.getHeader());
    8. conf.options().copyDefaults(true);
    9. try {
    10. config.save(new File(getDataFolder(), "config.yml"));
    11. } catch (IOException e2) {
    12. e2.printStackTrace();
    13. }
    14.  
    15. }
    16.  

    3) Using it in a listener by Example :
    Code:java
    1.  
    2. /************************************************************************
    3.  * This file is part of WarpSign.
    4.  *
    5.  * WarpSign is free software: you can redistribute it and/or modify
    6.  * it under the terms of the GNU General Public License as published by
    7.  * the Free Software Foundation, either version 3 of the License, or
    8.  * (at your option) any later version.
    9.  *
    10.  * WarpSign is distributed in the hope that it will be useful,
    11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13.  * GNU General Public License for more details.
    14.  *
    15.  * You should have received a copy of the GNU General Public License
    16.  * along with WarpSign. If not, see <[url]http://www.gnu.org/licenses/>[/url].
    17.  ************************************************************************/
    18. package be.Balor.WarpSign.Listeners;
    19.  
    20. import org.bukkit.block.Sign;
    21. import org.bukkit.event.EventHandler;
    22. import org.bukkit.event.EventPriority;
    23. import org.bukkit.event.Listener;
    24. import org.bukkit.event.block.BlockBreakEvent;
    25.  
    26. import be.Balor.Manager.Permissions.PermissionManager;
    27. import be.Balor.WarpSign.ConfigEnum;
    28.  
    29. /**
    30.  * @author Balor (aka Antoine Aflalo)
    31.  *
    32.  */
    33. public class SignListener implements Listener {
    34.  
    35. @EventHandler(priority = EventPriority.NORMAL)
    36. public void onBlockBreak(BlockBreakEvent event) {
    37. if (event.isCancelled())
    38. return;
    39. if (!(event.getBlock().getState() instanceof Sign))
    40. return;
    41. Sign sign = (Sign) event.getBlock().getState();
    42. if (sign.getLine(0).indexOf(ConfigEnum.KEYWORD.getString()) != 0)
    43. return;
    44. if (!PermissionManager.hasPerm(event.getPlayer(), "admincmd.warpsign.edit"))
    45. event.setCancelled(true);
    46.  
    47. }
    48.  
    49. }
    50.  


    The Idea is quite simple :
    Code:java
    1.  
    2. ConfigEnum.ENUM_VALUE_YOU_DEFINED.getTYPE();
    3.  

    Where of course ENUM_VALUE_YOU_DEFINED is the name of the Enum item.
    And TYPE = Int OR String OR Long OR Double.
    bigbeno37 likes this.
  18. Offline

    Don Redhorse

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Nice one @Dark_Balor similar to my approach.. need to work more on it..

    didn't know you were back at coding..

    This post has been edited 1 time. It was last edited by Don Redhorse Jan 23, 2012.
  19. Offline

    Dark_Balor

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I never left. I just didn't had the time to maintain my plugins and adding new functionality ... Thanks for taking the Tomb Plugin :)

    Right now I just maintain VirtualChest and work on AdminCmd (quite taking a lot of time ...). This part of the code is for an addon of AdminCmd.

    Before I forgot here is the output (the config file) of the code :
    Code:
    # This is the configuration file of WarpSign
    # warpKeyWord    :    set the keyword used to recognise a WarpSign.
    #  BE CAREFULL if you change it, older WarpSign will be not working. (Default : [ACWarp])
    # autoComplete    :    when typing the name of a world of a warp, if set to true, will autocomplete the Sign. (Default : true)
    # worldNotFound    :    Message used when using the autoComplete feature and the World couldn't be found. (Default : This World doesn't exists : )
    # warpNotFound    :    Message used when using the autoComplete feature and the Warp couldn't be found. (Default : This Warp doesn't exists : )
    # useColor    :    When set to true, will automatically color the World and Warp name on the sign using the color defined below. (Default : true)
    # wordColor    :    This color will be use for colouring the Word's name on the sign. (Default : &6)
    # warpColor    :    This color will be use for colouring the Warp's name on the sign. (Default : &a)
    # useCount    :    When set to true, the last line of the sign is used to count the number of teleportation done using the sign. (Default : true)
    # countMessage    :    When Count is set to true, this message will be used to display the teleport count. (Default : &cCount: &d)
    # teleportMessage    :    Teleport message used when successfully teleported to the Warp Point. (Default : &aTeleported successfully to &f)
    
    warpKeyWord: '[ACWarp]'
    autoComplete: true
    worldNotFound: 'This World doesn''t exists : '
    warpNotFound: 'This Warp doesn''t exists : '
    useColor: true
    wordColor: '&6'
    warpColor: '&a'
    useCount: true
    countMessage: '&cCount: &d'
    teleportMessage: '&aTeleported successfully to &f'
    
  20. Offline

    Don Redhorse

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    well I hope to get somewhere further today with my new concept.

    the problem really is to make it easy for somebody else to use, my aim is similar to this:

    Code:
    # TheMonkeyPack 0.1 by [Don Redhorse]
    #
    # Configuration File for TheMonkeyPack.
    #
    # For detailed assistance please visit: http://dev.bukkit.org/server-mods/monkey-pack/
     
    #------- Default Configuration
     
    # Configuration Version
    configVer: '1.0'
     
    # Error Log Enabled
    # Enable logging to server console
    # Warning and Severe will still be logged.
    errorLogEnabled: true
     
    # Debug Log Enabled
    # Enable more logging.. could be messy!
    DebugLogEnabled: true
     
    # Check for Update
    # Will check if there is a new version of the plugin out.
    checkForUpdate: true
     
    # Auto Update Config
    # This will overwrite any changes outside the configuration parameters!
    autoUpdateConfig: false
     
    # Save Config
    # This will overwrite any changes outside the configuration parameters!
    # Only needed if you use ingame commands to change the configuration.
    saveConfig: false
     
     
    # ------- Translation Features
     
    # Almost everything player visible (except admin commands) can be translated!
    # Please change to your liking and use the following variables
    # %perm = permission, %cmd = command, %Description = command description
     
    # NOTE: You need to use '' if you want to use ' in this text!
     
    # Message displayed when the permission is denied to use that command
    permDenied: 'You need the permission %perm to use the %cmd command which %Description !'
    # Message displayed when the wrong syntax for that command was used
    wrongSyntax: 'You used the wrong syntax for the command %cmd'
    # Message displayed when the right syntax for that command was used
    rightSyntax: 'The right syntax for this command is '
    # Message displayed when the explanation of the command is shown
    allowsYouTo: 'which allows you to %Description.'
    # Message displayed when the example of the command is shown
    example: 'An example for the command is '
     
    #-------- Module Configuration
     
    # Enable the different modules here or via
    # /mtp enable [MODULENAME]
     
    # After that you need to reload the server or use
    # /mtp reload
    # to create the config files for the different modules
     
    # So you still need to configure THEM!
     
    #-------- Module [AFK Handler] --------
     
    # Kick, Announce, GOD mode when AFK
    enableRARP: false
     
    #-------- Module [HelloWorld] --------
     
    # Announce which world you entered
    enableHelloWorld: false
     
    #-------- Module [Lampstone] --------
     
    # Switch between different blocks between day and night
    enableLampstone: false
     
    #-------- Module [Wurkit] --------
     
    # Earn Money when you build or destroy stuff
    enableGetPayed: false
     
    #-------- Module [Kits] --------
     
    # Give out kits to your players
    enableKits: true
    
  21. Offline

    Darkhand81

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    A class that would let you make a config like that, that you could just drop-into your project would be a dream come true. :)
  22. Offline

    Don Redhorse

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    or a nightmare.... at least for me coding it... I think it will come down to several classes though... one for the config (an enum similar to the stuff Dark_Balor posted), one for the messages (also an enum to support translation) and than one class which extends a base class in which you could define other stuff.

    major benefit of this would be that almost everything would be automatic, loading, saving, reloading, updating etc.. you just needed to call the methods.

    My major problem is that I'm not that good at coding... so I probably do it in an arkward way... wonder if I should just let people handle the creating of the config by making a call per line to a method or similar...

    hmm....

    perhaps the better way..
  23. Offline

    Darkhand81

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I'm still having trouble getting values from my config, I can tell that it's a simple issue but thanks to my extreme noobishness and trying to learn in the middle of this event system conversion, it's throwing me off. :)

    Still using the old system, and trying to use guynextdoor's methods. Since I'm still extending JavaPlugin, whenever I try to use config.getInt("blah.blah") for example, Eclipse is complaining under config: "The field JavaPlugin.config is not visible".

    So when I'm declaring config at the top of my onEnable here:
    Code:
    final FileConfiguration config = this.getConfig();
    My guess is that I need to reference config from somewhere other than "this"?

    This post has been edited 6 times. It was last edited by Darkhand81 Jan 25, 2012.
  24. Offline

    Sagacious_Zed Bukkit Docs

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @Darkhand81 make sure it is inside onEnable. If not, since technically JavaPlugin already has an config field, then you should choose a different name. fyi the private config variable is what you get when you call getConfig().
  25. Offline

    Darkhand81

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Ah ha! I wasn't aware of the already existing field. Thanks!

    I still can't access it outside of the class though (or even outside the onEnable method). Do I need some sort of getter method to access it outside of onEnable?

    This post has been edited 1 time. It was last edited by Darkhand81 Jan 25, 2012.
  26. Offline

    Don Redhorse

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    well you need to declare the variable outside of onEnable() normaly after your first { and before any method.

    if you do it the way you described that variable is I think called a field(?) (doesn't matter really) and only accessible in that method.

    so the best way to declare it would be

    private FileConfiguration config;

    than in onEnable()

    config = this.getConfig();

    and afterwards you would have a getter

    public FileConfiguration getConfig(){
    return config;
    }
  27. Offline

    Sagacious_Zed Bukkit Docs

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I disagree, that is not the best way to do it. I would put the above example down as what NOT to do. When you inherit JavaPlugin you inherited its getConfig() method, if you override it bad things happen if you are not aware of it.

    Something like this as the main class should work well enough.
    Code:java
    1. public PluginMain extends JavaPlugin {
    2. // JavaPlugin requires you to implement two methods onEnable and onDisable
    3. public void onEnable() {
    4. final FileConfiguration config = this.getConfig();
    5. config.getString("Hello.World");
    6. // more things to enable
    7. }
    8.  
    9. public void onDisable() {
    10. }
    11. }


    If you need to get the the configObject outside of this class, you can call this classes getConfig() method.

    This post has been edited 3 times. It was last edited by Sagacious_Zed Jan 25, 2012.
  28. Offline

    Darkhand81

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    That's what's throwing me for some reason, do you happen to have an example?

    This post has been edited 1 time. It was last edited by Darkhand81 Jan 26, 2012.
  29. Offline

    Don Redhorse

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    where was I overriding it? (me <== noob)

    Problem with the above is that you need to do

    private PluginName plugin = PluginName.getInstance(); or similar and
    private FileConfiguration config = plugin.getConfig();

    in the other class to be able to use it (or create a static getter) with

    config.getInt("yournode");

    which is honestly stupid..

    by far better would be to just get all values from the config in one class and make them accesable via getters and setters from other classes.

    at least I think
  30. Offline

    Sagacious_Zed Bukkit Docs

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @Don Redhorse
    Anytime you define a method with the same name and signature as that of a parent class you override the method.
    Anytime you define a method with the same name but different signature you over load the method.

    In general you should not assign the returned value from getConfig() to a class field. The short reason is that getConfig does not have to return the same object every time it is called. And it's proper encapsulation to be passing plugin into a class that needs to know about it.

    And yes, it's a completely valid approach to create a class with methods that always grab a particular value, but it can also be very verbose to write. So often i take the mid ground approach, i define an enum with the constants i am using as keys in my yaml.

Share This Page