From 3f6c5b1cd597b21bcad7b95b6f95535f1ae14d31 Mon Sep 17 00:00:00 2001 From: gamerforEA Date: Thu, 17 Jan 2019 20:07:27 +0400 Subject: [PATCH] Improve config utilities --- build.gradle | 2 +- .../gamerforea/eventhelper/EventHelper.java | 8 + .../command/CommandReloadAllConfigs.java | 32 ++ .../eventhelper/config/ConfigUtils.java | 289 ++++++++++-------- 4 files changed, 208 insertions(+), 123 deletions(-) create mode 100644 src/main/java/com/gamerforea/eventhelper/command/CommandReloadAllConfigs.java diff --git a/build.gradle b/build.gradle index 977aeac..2238b2a 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ apply plugin: 'forge' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' -version = "1.7.10-1.9" +version = "1.7.10-1.10" group= "com.gamerforea" archivesBaseName = "EventHelper" diff --git a/src/main/java/com/gamerforea/eventhelper/EventHelper.java b/src/main/java/com/gamerforea/eventhelper/EventHelper.java index f1106f2..1c5df85 100644 --- a/src/main/java/com/gamerforea/eventhelper/EventHelper.java +++ b/src/main/java/com/gamerforea/eventhelper/EventHelper.java @@ -1,5 +1,6 @@ package com.gamerforea.eventhelper; +import com.gamerforea.eventhelper.command.CommandReloadAllConfigs; import com.gamerforea.eventhelper.config.ConfigUtils; import com.gamerforea.eventhelper.inject.InjectionManager; import com.google.common.collect.Lists; @@ -7,6 +8,7 @@ import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLServerStartedEvent; +import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraftforge.common.config.Configuration; @@ -36,6 +38,12 @@ public final class EventHelper public static boolean explosions = true; public static boolean debug = true; + @EventHandler + public void onServerStart(FMLServerStartingEvent event) + { + event.registerServerCommand(new CommandReloadAllConfigs()); + } + @EventHandler public final void serverStarted(FMLServerStartedEvent event) { diff --git a/src/main/java/com/gamerforea/eventhelper/command/CommandReloadAllConfigs.java b/src/main/java/com/gamerforea/eventhelper/command/CommandReloadAllConfigs.java new file mode 100644 index 0000000..5f84a3c --- /dev/null +++ b/src/main/java/com/gamerforea/eventhelper/command/CommandReloadAllConfigs.java @@ -0,0 +1,32 @@ +package com.gamerforea.eventhelper.command; + +import com.gamerforea.eventhelper.config.ConfigUtils; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; + +public final class CommandReloadAllConfigs extends CommandBase +{ + private static final String NAME = "reloadallconfigs"; + + @Override + public String getCommandName() + { + return NAME; + } + + @Override + public String getCommandUsage(ICommandSender sender) + { + return '/' + NAME; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) + { + for (String configName : ConfigUtils.reloadAllConfigs()) + { + sender.addChatMessage(new ChatComponentText(configName + " config has been reloaded")); + } + } +} diff --git a/src/main/java/com/gamerforea/eventhelper/config/ConfigUtils.java b/src/main/java/com/gamerforea/eventhelper/config/ConfigUtils.java index 3b23515..462ea6d 100644 --- a/src/main/java/com/gamerforea/eventhelper/config/ConfigUtils.java +++ b/src/main/java/com/gamerforea/eventhelper/config/ConfigUtils.java @@ -10,6 +10,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.File; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.*; @@ -19,6 +20,23 @@ public final class ConfigUtils private static final String PACKAGE_DEFAULT = "default"; private static final Set> LOADED_CONFIG_CLASSES = new HashSet<>(); + public static Set reloadAllConfigs() + { + Set configNames = new TreeSet<>(); + for (Class configClass : LOADED_CONFIG_CLASSES) + { + try + { + readConfig(configClass, true); + configNames.add(getConfigName(configClass)); + } + catch (Throwable ignored) + { + } + } + return configNames; + } + @Nonnull public static > T readStringCollection( @Nonnull Configuration cfg, @@ -69,138 +87,165 @@ public static void readConfig(@Nonnull Class configClass, @Nonnull String con { for (Field field : configClass.getDeclaredFields()) { - int modifiers = field.getModifiers(); - if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) + try { - Class type = field.getType(); - if (type == boolean.class) - { - ConfigBoolean annotation = field.getAnnotation(ConfigBoolean.class); - if (annotation != null) - { - String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); - tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); - - boolean defaultValue = field.getBoolean(null); - boolean value = cfg.getBoolean(name, annotation.category(), defaultValue, annotation.comment()); - field.setBoolean(null, value); - } - } - else if (type == float.class) - { - ConfigFloat annotation = field.getAnnotation(ConfigFloat.class); - if (annotation != null) - { - String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); - tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); - - float defaultValue = field.getFloat(null); - float value = cfg.getFloat(name, annotation.category(), defaultValue, annotation.min(), annotation.max(), annotation.comment()); - field.setFloat(null, value); - } - } - else if (type == int.class) - { - ConfigInt annotation = field.getAnnotation(ConfigInt.class); - if (annotation != null) - { - String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); - tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); - - int defaultValue = field.getInt(null); - int value = cfg.getInt(name, annotation.category(), defaultValue, annotation.min(), annotation.max(), annotation.comment()); - field.setInt(null, value); - } - } - else if (type == String.class) - { - ConfigString annotation = field.getAnnotation(ConfigString.class); - if (annotation != null) - { - String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); - tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); - - String defaultValue = (String) field.get(null); - String value = cfg.getString(name, annotation.category(), defaultValue, annotation.comment()); - field.set(null, value); - } - } - else if (type == ItemBlockList.class) - { - ConfigItemBlockList annotation = field.getAnnotation(ConfigItemBlockList.class); - if (annotation != null) - { - String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); - tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); - - ItemBlockList list = (ItemBlockList) field.get(null); - Objects.requireNonNull(list, "ItemBlockList " + configClass.getName() + '.' + field.getName() + " must not be null"); - Set values = readStringCollection(cfg, name, annotation.category(), annotation.comment(), new HashSet<>(list.getRaw())); - list.clear(); - list.addRaw(values); - } - } - else if (type == ClassSet.class) - { - ConfigClassSet annotation = field.getAnnotation(ConfigClassSet.class); - if (annotation != null) - { - String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); - tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); - - ClassSet classSet = (ClassSet) field.get(null); - Objects.requireNonNull(classSet, "ClassSet " + configClass.getName() + '.' + field.getName() + " must not be null"); - Set values = readStringCollection(cfg, name, annotation.category(), annotation.comment(), new HashSet<>(classSet.getRaw())); - classSet.clear(); - classSet.addRaw(values); - } - } - else if (Enum.class.isAssignableFrom(type)) - { - ConfigEnum annotation = field.getAnnotation(ConfigEnum.class); - if (annotation != null) - { - String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); - tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); - - Enum defaultValue = (Enum) field.get(null); - Objects.requireNonNull(defaultValue, "Enum " + configClass.getName() + '.' + field.getName() + " must not be null"); - String valueName = cfg.getString(name, annotation.category(), defaultValue.name(), annotation.comment()); - try - { - Enum value = Enum.valueOf(defaultValue.getDeclaringClass(), valueName); - field.set(null, value); - } - catch (IllegalArgumentException e) - { - e.printStackTrace(); - } - } - } - else if (Collection.class.isAssignableFrom(type)) - { - // TODO Check generic type - ConfigStringCollection annotation = field.getAnnotation(ConfigStringCollection.class); - if (annotation != null) - { - String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); - tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); - - Collection collection = (Collection) field.get(null); - Objects.requireNonNull(collection, "Collection " + configClass.getName() + '.' + field.getName() + " must not be null"); - readStringCollection(cfg, name, annotation.category(), annotation.comment(), collection); - } - } + readConfigProperty(cfg, field); + } + catch (Throwable throwable) + { + EventHelper.LOGGER.error("Failed reading property {} in config {}", field, cfg.getConfigFile().getName(), throwable); } } } catch (Throwable throwable) { - EventHelper.LOGGER.error("Failed reading config " + cfg.getConfigFile().getName(), throwable); + EventHelper.LOGGER.error("Failed reading config {}", cfg.getConfigFile().getName(), throwable); } cfg.save(); } + private static void readConfigProperty(@Nonnull Configuration cfg, @Nonnull Field field) + throws IllegalAccessException + { + if (Modifier.isStatic(field.getModifiers())) + { + field.setAccessible(true); + for (Annotation declaredAnnotation : field.getDeclaredAnnotations()) + { + // Handle all annotations to throw expection if field have multiple config annotations + + Class annotationType = declaredAnnotation.annotationType(); + if (annotationType == ConfigBoolean.class) + { + checkType(field, boolean.class); + checkNotFinal(field); + + ConfigBoolean annotation = (ConfigBoolean) declaredAnnotation; + String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); + tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); + + boolean defaultValue = field.getBoolean(null); + boolean value = cfg.getBoolean(name, annotation.category(), defaultValue, annotation.comment()); + field.setBoolean(null, value); + } + else if (annotationType == ConfigFloat.class) + { + checkType(field, float.class); + checkNotFinal(field); + + ConfigFloat annotation = (ConfigFloat) declaredAnnotation; + String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); + tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); + + float defaultValue = field.getFloat(null); + float value = cfg.getFloat(name, annotation.category(), defaultValue, annotation.min(), annotation.max(), annotation.comment()); + field.setFloat(null, value); + } + else if (annotationType == ConfigInt.class) + { + checkType(field, int.class); + checkNotFinal(field); + + ConfigInt annotation = (ConfigInt) declaredAnnotation; + String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); + tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); + + int defaultValue = field.getInt(null); + int value = cfg.getInt(name, annotation.category(), defaultValue, annotation.min(), annotation.max(), annotation.comment()); + field.setInt(null, value); + } + else if (annotationType == ConfigString.class) + { + checkType(field, String.class); + checkNotFinal(field); + + ConfigString annotation = (ConfigString) declaredAnnotation; + String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); + tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); + + String defaultValue = (String) field.get(null); + String value = cfg.getString(name, annotation.category(), defaultValue, annotation.comment()); + field.set(null, value); + } + else if (annotationType == ConfigItemBlockList.class) + { + checkType(field, ItemBlockList.class); + + ConfigItemBlockList annotation = (ConfigItemBlockList) declaredAnnotation; + String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); + tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); + + ItemBlockList list = (ItemBlockList) field.get(null); + Objects.requireNonNull(list, field + " value must not be null"); + Set values = readStringCollection(cfg, name, annotation.category(), annotation.comment(), new HashSet<>(list.getRaw())); + list.clear(); + list.addRaw(values); + } + else if (annotationType == ConfigClassSet.class) + { + checkType(field, ClassSet.class); + + ConfigClassSet annotation = (ConfigClassSet) declaredAnnotation; + String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); + tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); + + ClassSet classSet = (ClassSet) field.get(null); + Objects.requireNonNull(classSet, field + " value must not be null"); + Set values = readStringCollection(cfg, name, annotation.category(), annotation.comment(), new HashSet<>(classSet.getRaw())); + classSet.clear(); + classSet.addRaw(values); + } + else if (annotationType == ConfigEnum.class) + { + checkType(field, Enum.class); + checkNotFinal(field); + + ConfigEnum annotation = (ConfigEnum) declaredAnnotation; + String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); + tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); + + Enum defaultValue = (Enum) field.get(null); + Objects.requireNonNull(defaultValue, field + " value must not be null"); + String valueName = cfg.getString(name, annotation.category(), defaultValue.name(), annotation.comment()); + try + { + Enum value = Enum.valueOf(defaultValue.getDeclaringClass(), valueName); + field.set(null, value); + } + catch (IllegalArgumentException e) + { + e.printStackTrace(); + } + } + else if (annotationType == ConfigStringCollection.class) + { + // TODO Check generic type + checkType(field, Collection.class); + + ConfigStringCollection annotation = (ConfigStringCollection) declaredAnnotation; + String name = annotation.name().isEmpty() ? field.getName() : annotation.name(); + tryMoveProperty(cfg, name, annotation.category(), annotation.oldName(), annotation.oldCategory()); + + Collection collection = (Collection) field.get(null); + Objects.requireNonNull(collection, field + " value must not be null"); + readStringCollection(cfg, name, annotation.category(), annotation.comment(), collection); + } + } + } + } + + private static void checkType(@Nonnull Field field, @Nonnull Class expectedType) + { + Class type = field.getType(); + Preconditions.checkArgument(expectedType == type || expectedType.isAssignableFrom(type), field + " type must be " + expectedType + " ( real type is " + type + ')'); + } + + private static void checkNotFinal(@Nonnull Field field) + { + int modifiers = field.getModifiers(); + Preconditions.checkArgument(!Modifier.isFinal(modifiers), field + " must not be final"); + } + private static boolean tryMoveProperty( @Nonnull Configuration cfg, @Nonnull String newName,