I know i have this as a small section in my other config tutorial, but in this tutorial i will go into more detail and tell you everything you need to make this work because recently i have seen a few people who have a small problem which can easily be fixed but it's nice not to have the errors to start with. This is a tutorial for new developers (i hope experienced devs dont have this problem , not that it would matter of they do) and so i will break it down as much as i can. So to start off we shall make a very basic main class. Code:java public class ConfigExample extends JavaPlugin { @Overridepublic void onDisable() { } @Overridepublic void onEnable() { }} Ok, what this plugin will do is it will send a player a message which is defined in the config when they log in, or when they use the command we will make. So to start off, we shall make our config in our onEnable method Code:java public class ConfigExample extends JavaPlugin { @Overridepublic void onDisable() { } @Overridepublic void onEnable() { final FileConfiguration config = this.getConfig(); config.addDefault("Message.to.send", "Hello, this is our message to send"); config.options().copyDefaults(true);saveConfig();} } Just to break it down, Code:java final FileConfiguration config = this.getConfig(); this line is defining our config so we can use it. Code:java config.addDefault("Message.to.send", "Hello, this is our message to send"); this line is adding a default line when the config is made, with the path Message.to.send and a string value. Code:java config.options().copyDefaults(true);saveConfig(); When a config is made, it initially is blank, but when you have these lines, they add in the defaults you have specified above. Ok, now we shall make a listener, so we can send the message to a player who joins the server. Note: this is a separate class. Right, before i go rushing off to make the event bit, i want to emphasize the constructor. Most people when they make a separate listener, will have their plugin variable, but they wont assign it to anything. And so what the constructor is doing, is assigning that plugin variable to our main class. Note: without the constructor, your plugin variable will return null and you WILL get a Nullpointer Exception. Code:java public class ConfigListener implements Listener{ConfigExample plugin; public ConfigListener(ConfigExample instance) {plugin = instance;} } Ok, so now that the constructor is sorted, we can move on to sending the message to the player when they log onto the server. To do this we are going to use a PlayerJoinEvent. Code:java public class ConfigListener implements Listener {ConfigExample plugin; public ConfigListener(ConfigExample instance) {plugin = instance;} @EventHandlerpublic void onJoin(PlayerJoinEvent e) {Player player = e.getPlayer(); player.sendMessage(plugin.getConfig().getString("Message.to.send"));}} The lines: Code:java @EventHandlerpublic void onJoin(PlayerJoinEvent e) { Are used to tell the plugin, 'Hey, we're going to use an event, of which is going to be a PlayerJoinEvent, and we have callled that event 'e'. Note how Code:java @EventHandler Doesnt have anything after it, this basically means that the event it is of default priority. The line: Code:java Player player = e.getPlayer(); Is making a player variable, so whenever we type 'player' in our event, it will refer to the player that was involved in the event, which in this case is the person who logged on. The line: Code:java player.sendMessage(plugin.getConfig().getString("Message.to.send")); Is what we are using to send the message to our player. See here how we are getting our config: Code:java plugin.getConfig().getString("Message.to.send") we are referring to our plugin variable which we made earlier, and we are getting our string to send to the player from our config, by using Code:java getString("Message.to.send") The lines in the "", i.e the "Message.to.send" is the path to the variable in your config. Note how the path is the same as we made earlier: Code:java config.addDefault("Message.to.send", "Hello, this is our message to send"); Code:java plugin.getConfig().getString("Message.to.send") If they were different, then we would not get the message we want. Now that we have our event and message set up, we should register our event in our onEnable, otherwise all our lovely code is made useless. To do this we simply do this: Code:java @Overridepublic void onEnable() { final FileConfiguration config = this.getConfig(); config.addDefault("Message.to.send", "Hello, this is our message to send"); config.options().copyDefaults(true);saveConfig(); PluginManager pm = getServer().getPluginManager();pm.registerEvents(new ConfigListener(this), this);} The lines which are registering the event and letting our beautiful code happen is: Code:java PluginManager pm = getServer().getPluginManager();pm.registerEvents(new ConfigListener(this), this); Note how i use registerEvents, this is registering all our events in our listener. This is particularly nice if were to have many events. Now lets export our plugin and see if it works so far: Yes, it does. Now, lets say we want to change that message in a command. How could we go about doing that? Well, lets make a new command: In our onEnable we shall add this Code:java getCommand("setmessage").setExecutor(new ConfigCommand(this)); So your onEnable now looks something like this: Code:java @Overridepublic void onEnable() { final FileConfiguration config = this.getConfig(); config.addDefault("Message.to.send", "Hello, this is our message to send"); config.options().copyDefaults(true);saveConfig(); PluginManager pm = getServer().getPluginManager();pm.registerEvents(new ConfigListener(this), this); getCommand("setmessage").setExecutor(new ConfigCommand(this));} Now, lets make our ConfigCommand class. now when i first make my class, it looks like this: Code:java package me.theguynextdoor.configexample; import org.bukkit.command.Command;import org.bukkit.command.CommandExecutor;import org.bukkit.command.CommandSender; public class ConfigCommand implements CommandExecutor { @Overridepublic boolean onCommand(CommandSender arg0, Command arg1, String arg2, String[] arg3) {// TODO Auto-generated method stubreturn false;} } So, lets make our constructor and rename some of those command variable names. So it now looks something like: Code:java package me.theguynextdoor.configexample; import org.bukkit.command.Command;import org.bukkit.command.CommandExecutor;import org.bukkit.command.CommandSender; public class ConfigCommand implements CommandExecutor {ConfigExample plugin; public ConfigCommand(ConfigExample instance) {plugin = instance;} @Overridepublic boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {return false;} } Lets make our basic command then which will change the message in our config. The way this command will work is that it will set the message to anything you type after the command. The command once i had finished it looks like this: Code:java @Overridepublic boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {if (cmd.getName().equalsIgnoreCase("setmessage")) {if (sender instanceof Player) { if (args.length == 0) {return false;} String msg; StringBuilder sb = new StringBuilder();for (int i = 0; i < args.length; i++) {if (i != 0)sb.append(' ');sb.append(args);}msg = sb.toString(); sender.sendMessage("The message has been changed to: " + msg);plugin.getConfig().set("Message.to.send", msg);plugin.saveConfig(); return true;}}return false;} Now lets break down the command First off, i checked that the name of the command was setmessage, by doing a simple if statement: Code:java if (cmd.getName().equalsIgnoreCase("setmessage")) { After that i checked that the person who sent the command was a player, by doing another if statement: Code:java if (sender instanceof Player) { After that i checked that they actually typed something for their message by checking if the argument length was 0. Because if they argument length was 0 then they obviously didn't type anything. To do this, i typed: Code:java if (args.length == 0) {return false;} When i type return false, it tells the command that it didnt work right, and so the command will send the user the usage message which will be in the plugin.yml which i will get to in a second. Now, how do know how many arguments they put? Cant we just set the message to args[1] + args[2] ... The answer is no. So what we will be using is what is known as a string builder. The string builder looks like this: Code:java String msg; StringBuilder sb = new StringBuilder();for (int i = 0; i < args.length; i++) {if (i != 0)sb.append(' ');sb.append(args);}msg = sb.toString(); So now all we have to do, is set our Message.to.send variable in our config to msg. To do this we can simply do: Code:java plugin.getConfig().set("Message.to.send", msg);plugin.saveConfig(); Note: You must not forget to do the plugin.saveConfig(); because without this the config will not save and your command might as well not be there. And just to assure the player that their command has worked, we will send them a little message: Code:java sender.sendMessage("The message has been changed to: " + msg); Now the command total looks like this: Code:java @Overridepublic boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {if (cmd.getName().equalsIgnoreCase("setmessage")) {if (sender instanceof Player) { if (args.length == 0) {return false;} String msg; StringBuilder sb = new StringBuilder();for (int i = 0; i < args.length; i++) {if (i != 0)sb.append(' ');sb.append(args);}msg = sb.toString(); sender.sendMessage("The message has been changed to: " + msg);plugin.getConfig().set("Message.to.send", msg);plugin.saveConfig(); return true;}}return false;} Now what we need to do is register the command in our plugin.yml This isnt a full plugin tutorial so i havent gone into the plugin.yml or how it works and what to put, but for this plugin my plugin.yml looks like this Code: name: ConfigExample main: me.theguynextdoor.configexample.ConfigExample version: 0.1 commands: setmessage: description: sets the message to send usage: /<command> <message> Now we should be able to change the message: Before using the command: Just after typing our command: After relogging after typing command: ------------------------------------------------Extra------------------------------------------------------ That is the main chunk of my tutorial done. Now what if we wanted colours? For colours: i.e when the player used &2 or &e they get colours. Doing this is rather simply. In our listener, when we send the message we add this to the end Code:java .replaceAll("(&([a-f0-9]))", "\u00A7$2") So our event now looks like this: Code:java @EventHandlerpublic void onJoin(PlayerJoinEvent e) {Player player = e.getPlayer(); player.sendMessage(plugin.getConfig().getString("Message.to.send").replaceAll("(&([a-f0-9]))", "\u00A7$2"));} We also add this to our command, Code:java sender.sendMessage("The message has been changed to: " + msg.replaceAll("(&([a-f0-9]))", "\u00A7$2"));plugin.getConfig().set("Message.to.send", msg.replaceAll("(&([a-f0-9]))", "\u00A7$2")); So our final command executor looks like this: Code:java package me.theguynextdoor.configexample; import org.bukkit.command.Command;import org.bukkit.command.CommandExecutor;import org.bukkit.command.CommandSender;import org.bukkit.entity.Player; public class ConfigCommand implements CommandExecutor {ConfigExample plugin; public ConfigCommand(ConfigExample instance) {plugin = instance;} @Overridepublic boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {if (cmd.getName().equalsIgnoreCase("setmessage")) {if (sender instanceof Player) { if (args.length == 0) {return false;} String msg; StringBuilder sb = new StringBuilder();for (int i = 0; i < args.length; i++) {if (i != 0)sb.append(' ');sb.append(args);}msg = sb.toString(); sender.sendMessage("The message has been changed to: " + msg.replaceAll("(&([a-f0-9]))", "\u00A7$2"));plugin.getConfig().set("Message.to.send", msg.replaceAll("(&([a-f0-9]))", "\u00A7$2"));plugin.saveConfig(); return true;}}return false;}} So now: And when joining: Thanks for reading
I followed the exact steps to making the configs but eclipse is telling me that "config" in my listeners is "config cannot be resolved or is not a field". Edit:// I fixed it by doing a shortcut. Instead of putting Code: @Override public void onEnable(){ final FileConfiguration config = this.getConfig(); i had to do this Code: public static FileConfiguration config; @Override public void onEnable(){ config = this.getConfig();
Holy crap, what a nice post. But what if I want to add comments to the config file? The Bukkit system tends to filter them out.. I extract the file from the .jar, then edit some values. When just extracted, the comments are there, and when saving, the comments disappear.
Thanks, but unfortunately when you save a config (in code i presume) then the comments get deleted. I wish there was a simple work around to this. I cant believe it isn't in the API at the moment, it should be pretty standard imo.
The only possible way is to type the config.yml yourself, then get they data from there (Not using config.addDefault()
Yea, I do that. And then export the file. BUT when I edit data afterwards the comments get removed anyway
the Configuration API does not handle inline comments. It is working as expected per design of dinnerbone.
I have a question for you, I want my message to be sent when the player is kicked, like a kick reason, I have the main bit of code that kicks the player for asking for what I have in code, but now I want to have people be able to edit the groups they ask for/ the kickmessage. Any help?
I'm using this, but I end up with a NPE.. Code: AlternativeExp plugin; public Exp(AlternativeExp instance) { plugin = instance; } Then I use like Code: plugin.getConfig(). bla bla bla but I get this error: Code: Caused by: java.lang.NullPointerException at me.SyTeck.AlternativeExp.Exp.onCommand(Exp.java:48) Line 48: Code: if(plugin.getConfig().getBoolean("RandomMode") == true) { Any suggestion? Maybe its the random thingy I use, it looks like this: Code: Random rand = new Random(); int exp = rand.nextInt(11); but I don't think so.
Since the error is in the onCommand, is there any chance i could see your whole main class, and command class?