Improve config handling: 1. Fix world configs stored under the wrong

name. 2. Add warnings if paths are used in world files that should only
or can only be set in the global configuration file.
This commit is contained in:
asofold 2012-09-14 14:52:15 +02:00
parent 9ec4cfaa15
commit 6d45a88c03
4 changed files with 177 additions and 5 deletions

View File

@ -23,6 +23,7 @@ public abstract class ConfPaths {
* , 88P , 88P , 88P
* "8",P" "8",P" "8",P"
*/
@GlobalConfig
private static final String LOGGING = "logging.";
public static final String LOGGING_ACTIVE = LOGGING + "active";
public static final String LOGGING_CONSOLE = LOGGING + "console";
@ -38,6 +39,7 @@ public abstract class ConfPaths {
* d8b Y8b Y8b 888 Y88D Y888 , 888 , 888 888 ,ee 888 888 888 888 , Y888 888P Y888 888P Y88D
* d888b Y8b Y8b 888 d,dP "88,e8' "YeeP" 888 888 "88 888 888 888 "YeeP" "88 88" "88 88" d,dP
*/
@GlobalConfig
private static final String MISCELLANEOUS = "miscellaneous.";
public static final String MISCELLANEOUS_ALLOWCLIENTMODS = MISCELLANEOUS + "allowclientmods";
public static final String MISCELLANEOUS_OPINCONSOLEONLY = MISCELLANEOUS + "opinconsoleonly";
@ -45,7 +47,6 @@ public abstract class ConfPaths {
public static final String MISCELLANEOUS_CHECKFORUPDATES = MISCELLANEOUS + "checkforupdates";
public static final String MISCELLANEOUS_READTIMEOUT = MISCELLANEOUS + "readtimeout";
public static final String MISCELLANEOUS_REPORTTOMETRICS = MISCELLANEOUS + "reporttometrics";
private static final String MISCELLANEOUS_NOMOVEDTOOQUICKLY = MISCELLANEOUS + "nomovedtooquickly.";
public static final String MISCELLANEOUS_NOMOVEDTOOQUICKLY_ENABLED = MISCELLANEOUS_NOMOVEDTOOQUICKLY + "enabled";
public static final String MISCELLANEOUS_NOMOVEDTOOQUICKLY_USEPROXY = MISCELLANEOUS_NOMOVEDTOOQUICKLY + "useproxy";
@ -70,7 +71,9 @@ public abstract class ConfPaths {
public static final String BLOCKBREAK_FASTBREAK_DEBUG = BLOCKBREAK_FASTBREAK + "debug";
private static final String BLOCKBREAK_FASTBREAK_BUCKETS = BLOCKBREAK + "buckets.";
public static final String BLOCKBREAK_FASTBREAK_BUCKETS_CONTENTION = BLOCKBREAK_FASTBREAK_BUCKETS + "contention";
@GlobalConfig
public static final String BLOCKBREAK_FASTBREAK_BUCKETS_N = BLOCKBREAK_FASTBREAK_BUCKETS + "number";
@GlobalConfig
public static final String BLOCKBREAK_FASTBREAK_BUCKETS_DUR = BLOCKBREAK_FASTBREAK_BUCKETS + "duration";
public static final String BLOCKBREAK_FASTBREAK_BUCKETS_FACTOR = BLOCKBREAK_FASTBREAK_BUCKETS + "factor";
public static final String BLOCKBREAK_FASTBREAK_DELAY = BLOCKBREAK_FASTBREAK + "delay";
@ -83,8 +86,10 @@ public abstract class ConfPaths {
public static final String BLOCKBREAK_FREQUENCY_MOD_CREATIVE = BLOCKBREAK_FREQUENCY + "intervalcreative";
public static final String BLOCKBREAK_FREQUENCY_MOD_SURVIVAL = BLOCKBREAK_FREQUENCY + "intervalsurvival";
private static final String BLOCKBREAK_FREQUENCY_BUCKETS = BLOCKBREAK_FREQUENCY + "buckets.";
@GlobalConfig
public static final String BLOCKBREAK_FREQUENCY_BUCKETS_DUR = BLOCKBREAK_FREQUENCY_BUCKETS + "duration";
public static final String BLOCKBREAK_FREQUENCY_BUCKETS_FACTOR = BLOCKBREAK_FREQUENCY_BUCKETS + "factor";
@GlobalConfig
public static final String BLOCKBREAK_FREQUENCY_BUCKETS_N = BLOCKBREAK_FREQUENCY_BUCKETS + "number";
private static final String BLOCKBREAK_FREQUENCY_SHORTTERM = BLOCKBREAK_FREQUENCY + "shortterm.";
public static final String BLOCKBREAK_FREQUENCY_SHORTTERM_LIMIT = BLOCKBREAK_FREQUENCY_SHORTTERM + "limit";
@ -169,6 +174,7 @@ public abstract class ConfPaths {
// globalchat
private static final String CHAT_GLOBALCHAT = CHAT + "globalchat.";
public static final String CHAT_GLOBALCHAT_CHECK = CHAT_GLOBALCHAT + "active";
public static final String CHAT_GLOBALCHAT_DEBUG = CHAT_GLOBALCHAT + "debug";
public static final String CHAT_GLOBALCHAT_LEVEL = CHAT_GLOBALCHAT + "level";
public static final String CHAT_GLOBALCHAT_ENGINE_MAXIMUM = CHAT_GLOBALCHAT + "maximum";
public static final String CHAT_GLOBALCHAT_FREQUENCY = CHAT_GLOBALCHAT + "frequency.";
@ -180,24 +186,29 @@ public abstract class ConfPaths {
private static final String CHAT_GLOBALCHAT_GL = CHAT_GLOBALCHAT + "global.";
public static final String CHAT_GLOBALCHAT_GL_CHECK = CHAT_GLOBALCHAT_GL + "active";
public static final String CHAT_GLOBALCHAT_GL_WEIGHT = CHAT_GLOBALCHAT_GL + "weight";
@GlobalConfig
public static final String CHAT_GLOBALCHAT_GL_WORDS = CHAT_GLOBALCHAT_GL + "words.";
public static final String CHAT_GLOBALCHAT_GL_WORDS_CHECK = CHAT_GLOBALCHAT_GL_WORDS + "active";
@GlobalConfig
public static final String CHAT_GLOBALCHAT_GL_PREFIXES = CHAT_GLOBALCHAT_GL + "prefixes.";
public static final String CHAT_GLOBALCHAT_GL_PREFIXES_CHECK = CHAT_GLOBALCHAT_GL_PREFIXES + "active";
@GlobalConfig
public static final String CHAT_GLOBALCHAT_GL_SIMILARITY = CHAT_GLOBALCHAT_GL + "similarity.";
public static final String CHAT_GLOBALCHAT_GL_SIMILARITY_CHECK = CHAT_GLOBALCHAT_GL_SIMILARITY + "active";
// Extended per player checks.
private static final String CHAT_GLOBALCHAT_PP = CHAT_GLOBALCHAT + "player.";
public static final String CHAT_GLOBALCHAT_PP_CHECK = CHAT_GLOBALCHAT_PP + "active";
public static final String CHAT_GLOBALCHAT_PP_WEIGHT = CHAT_GLOBALCHAT_PP + "weight";
@GlobalConfig
public static final String CHAT_GLOBALCHAT_PP_PREFIXES = CHAT_GLOBALCHAT_PP + "prefixes.";
public static final String CHAT_GLOBALCHAT_PP_PREFIXES_CHECK = CHAT_GLOBALCHAT_PP_PREFIXES + "active";
@GlobalConfig
public static final String CHAT_GLOBALCHAT_PP_WORDS = CHAT_GLOBALCHAT_PP + "words.";
public static final String CHAT_GLOBALCHAT_PP_WORDS_CHECK = CHAT_GLOBALCHAT_PP_WORDS + "active";
@GlobalConfig
public static final String CHAT_GLOBALCHAT_PP_SIMILARITY = CHAT_GLOBALCHAT_PP + "similarity.";
public static final String CHAT_GLOBALCHAT_PP_SIMILARITY_CHECK = CHAT_GLOBALCHAT_PP_SIMILARITY + "active";
// globalchat actions
public static final String CHAT_GLOBALCHAT_DEBUG = CHAT_GLOBALCHAT + "debug";
public static final String CHAT_GLOBALCHAT_ACTIONS = CHAT_GLOBALCHAT + "actions";
// nopwnage

View File

@ -15,6 +15,7 @@ import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.configuration.MemoryConfiguration;
import fr.neatmonster.nocheatplus.NoCheatPlus;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
@ -192,6 +193,8 @@ public class ConfigManager {
}
CheckUtils.fileLogger = logger;
final MemoryConfiguration worldDefaults = PathUtils.getWorldsDefaultConfig(globalConfig);
// Try to obtain and parse the world-specific configuration files.
final HashMap<String, File> worldFiles = new HashMap<String, File>();
if (plugin.getDataFolder().isDirectory())
@ -199,16 +202,18 @@ public class ConfigManager {
if (file.isFile()) {
final String fileName = file.getName();
if (fileName.matches(".+_config.yml$")) {
final String worldname = fileName.substring(0, fileName.length() - 10);
final String worldname = fileName.substring(0, fileName.length() - 11);
worldFiles.put(worldname, file);
}
}
for (final Entry<String, File> worldEntry : worldFiles.entrySet()) {
final File worldFile = worldEntry.getValue();
PathUtils.warnGlobalOnlyPaths(worldFile, worldEntry.getKey());
final ConfigFile worldConfig = new ConfigFile();
worldConfig.setDefaults(globalConfig);
worldConfig.setDefaults(worldDefaults);
worldConfig.options().copyDefaults(true);
try {
worldConfig.load(worldFile);
worldConfig.load(worldFile);
worldsMap.put(worldEntry.getKey(), worldConfig);
try{
worldConfig.save(worldFile);
@ -222,6 +227,8 @@ public class ConfigManager {
+ worldEntry.getKey() + " (see exception below). Continue with global default settings...");
e.printStackTrace();
}
worldConfig.setDefaults(globalConfig);
worldConfig.options().copyDefaults(true);
worldConfig.regenerateActionLists();
}
}

View File

@ -0,0 +1,19 @@
package fr.neatmonster.nocheatplus.config;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to indicate that a config path can only be set in the global configuration file.
* This can be added to parent fields, all other fields whose name starts with the name of the parent field will automatically be global only.
* @author asofold
*
*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GlobalConfig {
}

View File

@ -0,0 +1,135 @@
package fr.neatmonster.nocheatplus.config;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.MemoryConfiguration;
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.prefixtree.SimpleCharPrefixTree;
public class PathUtils {
/** Field names of ConfPaths. */
private static final Set<String> globalOnlyFields = new HashSet<String>();
/** Paths of ConfPaths (field values). */
private static final Set<String> globalOnlyPaths = new LinkedHashSet<String>();
private static final SimpleCharPrefixTree globalOnlyPrefixes = new SimpleCharPrefixTree();
static{
initGlobalOnlyPaths();
}
/**
* Test/evaluation of using annotations to confine config paths to the global config.
* @return
*/
private static void initGlobalOnlyPaths(){
globalOnlyFields.clear();
globalOnlyPaths.clear();
globalOnlyPrefixes.clear();
for (final Field field : ConfPaths.class.getDeclaredFields()){
final String name = field.getName();
if (field.isAnnotationPresent(GlobalConfig.class)){
globalOnlyFields.add(name);
addGlobalOnlyPath(field);
}
else{
for (final String refName : globalOnlyFields){
if (name.startsWith(refName) && field.getType() == String.class){
addGlobalOnlyPath(field);
}
}
}
}
}
private static void addGlobalOnlyPath(final Field field) {
try {
final String path = field.get(null).toString();
globalOnlyPaths.add(path);
globalOnlyPrefixes.feed(path);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
/**
* Warn on the console if paths are used.
* @param config
* @param paths
* @param msgHeader
*/
public static void warnPaths(ConfigFile config, Collection<String> paths, String msgPrefix){
final Logger log = Bukkit.getLogger();
for (final String path : config.getKeys(true)){
if (globalOnlyPrefixes.hasPrefix(path))
log.warning("[NoCheatPlus] Config path '" + path + "'" + msgPrefix);
}
}
/**
* Warn about paths that are only to be set in the global config.
* @param config
* @param paths
* @param configName
*/
public static void warnGlobalOnlyPaths(ConfigFile config, String configName){
warnPaths(config, globalOnlyPaths, " (" + configName + ") should only be set in the global configuration.");
}
public static void warnGlobalOnlyPaths(File file, String configName){
final ConfigFile config = new ConfigFile();
try {
config.load(file);
warnGlobalOnlyPaths(config, configName);
} catch (FileNotFoundException e) {
} catch (IOException e) {
} catch (InvalidConfigurationException e) {
}
}
/**
* A config file only containing the entries that are not set as global only.
* @param defaultConfig
* @return
*/
public static MemoryConfiguration getWorldsDefaultConfig(final ConfigFile defaultConfig){
final char sep = defaultConfig.options().pathSeparator();
final MemoryConfiguration config = new ConfigFile();
config.options().pathSeparator(sep);
final Map<String, Object> defaults = defaultConfig.getValues(false);
for (final Entry<String, Object> entry : defaults.entrySet()){
final String part = entry.getKey();
if (!part.isEmpty() && globalOnlyPrefixes.hasPrefix(part)) continue;
final Object value = entry.getValue();
if (value instanceof ConfigurationSection) addSection(config, (ConfigurationSection) value, part, sep);
else config.set(part, value);
}
return config;
}
public static void addSection(final MemoryConfiguration config, final ConfigurationSection section, final String path, final char sep) {
final Map<String, Object> values = section.getValues(false);
for (final Entry<String, Object> entry : values.entrySet()){
final String fullPath = path + sep + entry.getKey();
if (globalOnlyPrefixes.hasPrefix(fullPath)) continue;
final Object value = entry.getValue();
if (value instanceof ConfigurationSection) addSection(config, (ConfigurationSection) value, fullPath, sep);
else config.set(fullPath, value);
}
}
}