From c818ddff99927e5cee79ed58aa7df042540c9cb5 Mon Sep 17 00:00:00 2001 From: Brettflan Date: Fri, 22 Jul 2011 07:25:12 -0500 Subject: [PATCH] New command /f config [setting] [value] which can be used to change any conf.json setting. This is mainly for people who have trouble editing the file manually, for whatever reason. It even fixes any capitalization errors, and saves the conf.json file immediately after an option is changed. Can be run by player or from server console. Uses new permission node "factions.config". --- src/com/massivecraft/factions/Factions.java | 5 + .../factions/commands/FBaseCommand.java | 12 +- .../factions/commands/FCommandConfig.java | 225 ++++++++++++++++++ .../factions/commands/FCommandHelp.java | 1 + src/plugin.yml | 4 + 5 files changed, 239 insertions(+), 8 deletions(-) create mode 100644 src/com/massivecraft/factions/commands/FCommandConfig.java diff --git a/src/com/massivecraft/factions/Factions.java b/src/com/massivecraft/factions/Factions.java index 5d4ab97e..e10a0ee0 100644 --- a/src/com/massivecraft/factions/Factions.java +++ b/src/com/massivecraft/factions/Factions.java @@ -77,6 +77,7 @@ public class Factions extends JavaPlugin { commands.add(new FCommandBypass()); commands.add(new FCommandChat()); commands.add(new FCommandClaim()); + commands.add(new FCommandConfig()); commands.add(new FCommandCreate()); commands.add(new FCommandDeinvite()); commands.add(new FCommandDescription()); @@ -337,6 +338,10 @@ public class Factions extends JavaPlugin { return hasPerm(sender, "factions.lock"); } + public static boolean hasPermConfigure(CommandSender sender) { + return hasPerm(sender, "factions.config"); + } + public static boolean hasPermDisband(CommandSender sender) { return hasPerm(sender, "factions.disband"); } diff --git a/src/com/massivecraft/factions/commands/FBaseCommand.java b/src/com/massivecraft/factions/commands/FBaseCommand.java index 1bd3190c..60cc7cbc 100644 --- a/src/com/massivecraft/factions/commands/FBaseCommand.java +++ b/src/com/massivecraft/factions/commands/FBaseCommand.java @@ -1,6 +1,7 @@ package com.massivecraft.factions.commands; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.bukkit.command.CommandSender; @@ -229,15 +230,10 @@ public class FBaseCommand { return false; } + public static final List aliasTrue = new ArrayList(Arrays.asList("true", "yes", "y", "ok", "on", "+")); + public static final List aliasFalse = new ArrayList(Arrays.asList("false", "no", "n", "off", "-")); + public boolean parseBool(String str) { - List aliasTrue = new ArrayList(); - aliasTrue.add("true"); - aliasTrue.add("yes"); - aliasTrue.add("y"); - aliasTrue.add("ok"); - aliasTrue.add("on"); - aliasTrue.add("+"); - return aliasTrue.contains(str.toLowerCase()); } diff --git a/src/com/massivecraft/factions/commands/FCommandConfig.java b/src/com/massivecraft/factions/commands/FCommandConfig.java new file mode 100644 index 00000000..d7dea900 --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandConfig.java @@ -0,0 +1,225 @@ +package com.massivecraft.factions.commands; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Set; +import java.util.HashMap; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.Factions; + +public class FCommandConfig extends FBaseCommand { + + private static HashMap properFieldNames = new HashMap(); + + public FCommandConfig() { + aliases.add("config"); + + senderMustBePlayer = false; + + requiredParameters.add("setting"); + requiredParameters.add("value"); + + helpDescription = "change a conf.json setting"; + } + + @Override + public boolean hasPermission(CommandSender sender) { + return Factions.hasPermConfigure(sender); + } + + @Override + public void perform() { + + if( isLocked() ) { + sendLockMessage(); + return; + } + + // store a lookup map of lowercase field names paired with proper capitalization field names + // that way, if the person using this command messes up the capitalization, we can fix that + if (properFieldNames.isEmpty()) { + Field[] fields = Conf.class.getDeclaredFields(); + for(int i = 0; i < fields.length; i++) { + properFieldNames.put(fields[i].getName().toLowerCase(), fields[i].getName()); + } + } + + String fieldName = properFieldNames.get(parameters.get(0).toLowerCase()); + + if (fieldName == null || fieldName.isEmpty()) { + sendMessage("No configuration setting \""+parameters.get(0)+"\" exists."); + return; + } + + String success = ""; + + String value = parameters.get(1); + for(int i = 2; i < parameters.size(); i++) { + value += ' ' + parameters.get(i); + } + + try { + Field target = Conf.class.getField(fieldName); + + // boolean + if (target.getType() == boolean.class) { + if (aliasTrue.contains(value.toLowerCase())) { + target.setBoolean(null, true); + success = "\""+fieldName+"\" option set to true (enabled)."; + } + else if (aliasFalse.contains(value.toLowerCase())) { + target.setBoolean(null, false); + success = "\""+fieldName+"\" option set to false (disabled)."; + } + else { + sendMessage("Cannot set \""+fieldName+"\": boolean value required (true or false)."); + return; + } + } + + // int + else if (target.getType() == int.class) { + try { + int intVal = Integer.parseInt(value); + target.setInt(null, intVal); + success = "\""+fieldName+"\" option set to "+intVal+"."; + } + catch(NumberFormatException ex) { + sendMessage("Cannot set \""+fieldName+"\": integer (whole number) value required."); + return; + } + } + + // double + else if (target.getType() == double.class) { + try { + double doubleVal = Double.parseDouble(value); + target.setDouble(null, doubleVal); + success = "\""+fieldName+"\" option set to "+doubleVal+"."; + } + catch(NumberFormatException ex) { + sendMessage("Cannot set \""+fieldName+"\": double (numeric) value required."); + return; + } + } + + // String + else if (target.getType() == String.class) { + target.set(null, value); + success = "\""+fieldName+"\" option set to \""+value+"\"."; + } + + // ChatColor + else if (target.getType() == ChatColor.class) { + ChatColor newColor = null; + try { + newColor = ChatColor.valueOf(value.toUpperCase()); + } + catch (IllegalArgumentException ex) { + } + if (newColor == null) { + sendMessage("Cannot set \""+fieldName+"\": \""+value.toUpperCase()+"\" is not a valid color."); + return; + } + target.set(null, newColor); + success = "\""+fieldName+"\" color option set to \""+value.toUpperCase()+"\"."; + } + + // Set or other parameterized collection + else if (target.getGenericType() instanceof ParameterizedType) { + ParameterizedType targSet = (ParameterizedType)target.getGenericType(); + Type innerType = targSet.getActualTypeArguments()[0]; + + // not a Set, somehow, and that should be the only collection we're using in Conf.java + if (targSet.getRawType() != Set.class) { + sendMessage("\""+fieldName+"\" is not a data collection type which can be modified with this command."); + return; + } + + // Set + else if (innerType == Material.class) { + Material newMat = null; + try { + newMat = Material.valueOf(value.toUpperCase()); + } + catch (IllegalArgumentException ex) { + } + if (newMat == null) { + sendMessage("Cannot change \""+fieldName+"\" set: \""+value.toUpperCase()+"\" is not a valid material."); + return; + } + + Set matSet = (Set)target.get(null); + + // Material already present, so remove it + if (matSet.contains(newMat)) { + matSet.remove(newMat); + target.set(null, matSet); + success = "\""+fieldName+"\" set: Material \""+value.toUpperCase()+"\" removed."; + } + // Material not present yet, add it + else { + matSet.add(newMat); + target.set(null, matSet); + success = "\""+fieldName+"\" set: Material \""+value.toUpperCase()+"\" added."; + } + } + + // Set + else if (innerType == String.class) { + Set stringSet = (Set)target.get(null); + + // String already present, so remove it + if (stringSet.contains(value)) { + stringSet.remove(value); + target.set(null, stringSet); + success = "\""+fieldName+"\" set: \""+value+"\" removed."; + } + // String not present yet, add it + else { + stringSet.add(value); + target.set(null, stringSet); + success = "\""+fieldName+"\" set: \""+value+"\" added."; + } + } + + // Set of unknown type + else { + sendMessage("\""+fieldName+"\" is not a data type set which can be modified with this command."); + return; + } + } + + // unknown type + else { + sendMessage("\""+fieldName+"\" is not a data type which can be modified with this command."); + return; + } + } + catch (NoSuchFieldException ex) { + sendMessage("Configuration setting \""+fieldName+"\" couldn't be matched, though it should be... please report this error."); + return; + } + catch (IllegalAccessException ex) { + sendMessage("Error setting configuration setting \""+fieldName+"\" to \""+value+"\"."); + return; + } + + if (!success.isEmpty()) { + sendMessage(success); + if (sender instanceof Player) { + Factions.log(success + " Command was run by "+player.getName()+"."); + } + } + // save change to disk + Conf.save(); + } + +} diff --git a/src/com/massivecraft/factions/commands/FCommandHelp.java b/src/com/massivecraft/factions/commands/FCommandHelp.java index 0cca49f8..8a0633fd 100644 --- a/src/com/massivecraft/factions/commands/FCommandHelp.java +++ b/src/com/massivecraft/factions/commands/FCommandHelp.java @@ -147,6 +147,7 @@ public class FCommandHelp extends FBaseCommand { pageLines.add( new FCommandReload().getUseageTemplate() ); pageLines.add( new FCommandSaveAll().getUseageTemplate() ); pageLines.add( new FCommandVersion().getUseageTemplate() ); + pageLines.add( new FCommandConfig().getUseageTemplate() ); helpPages.add(pageLines); } diff --git a/src/plugin.yml b/src/plugin.yml index 7f4863af..4adb2a09 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -27,6 +27,7 @@ permissions: factions.disband: true factions.worldOptions: true factions.commandDisable.none: true + factions.config: true factions.participate: description: Allows the player to participate in a faction default: true @@ -57,6 +58,9 @@ permissions: factions.worldOptions: description: Can use the /f worldnoclaim and /f worldnopowerloss commands default: op + factions.config: + description: Can use /f config command to change conf.json options + default: op factions.commandDisable.none: description: no commands disabled (ignore all other commandDisable permissions) default: op