From ae96fd08db84e56cfe1e86f3004876b29c014a07 Mon Sep 17 00:00:00 2001 From: LexManos Date: Thu, 6 Apr 2017 13:15:26 -0700 Subject: [PATCH] Fix arrays in map values for config system --- .../common/config/ConfigManager.java | 67 +++++++++++-------- .../common/config/FieldWrapper.java | 19 ++++-- .../net/minecraftforge/debug/ConfigTest.java | 12 ++-- 3 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/config/ConfigManager.java b/src/main/java/net/minecraftforge/common/config/ConfigManager.java index fe2062e52..34f2712ef 100644 --- a/src/main/java/net/minecraftforge/common/config/ConfigManager.java +++ b/src/main/java/net/minecraftforge/common/config/ConfigManager.java @@ -50,6 +50,7 @@ public class ConfigManager { private static Map> asm_data = Maps.newHashMap(); static Map, ITypeAdapter> ADAPTERS = Maps.newHashMap(); + static Map, Class> ARRAY_REMAP = Maps.newHashMap(); private static Map CONFIGS = Maps.newHashMap(); private static Map>> MOD_CONFIG_CLASSES = Maps.newHashMap(); @@ -85,6 +86,16 @@ public class ConfigManager register(Integer[].class, TypeAdapters.IntA); register(String.class, TypeAdapters.Str); register(String[].class, TypeAdapters.StrA); + + + ARRAY_REMAP.put(Boolean.class, Boolean[].class ); + ARRAY_REMAP.put(Float.class, Float[].class ); + ARRAY_REMAP.put(Double.class, Double[].class ); + ARRAY_REMAP.put(Byte.class, Byte[].class ); + ARRAY_REMAP.put(Character.class, Character[].class); + ARRAY_REMAP.put(Short.class, Short[].class ); + ARRAY_REMAP.put(Integer.class, Integer[].class ); + ARRAY_REMAP.put(String.class, String[].class ); } private static void register(Class cls, ITypeAdapter adpt) { @@ -110,7 +121,7 @@ public class ConfigManager map.put(type, target); } } - + /** * Bounces to sync(). * TODO: remove @@ -123,13 +134,13 @@ public class ConfigManager /** * Synchronizes configuration data between the file on disk, the {@code Configuration} object and the annotated * mod classes containing the configuration variables. - * + * * When first called, this method will try to load the configuration from disk. If this fails, because the file * does not exist, it will be created with default values derived from the mods config classes variable default values * and comments and ranges, as well as configuration names based on the appropriate annotations found in {@code @Config}. - * + * * Note, that this method is being called by the {@link FMLModContaier}, so the mod needn't call it in init(). - * + * * If this method is called after the initial load, it will check whether the values in the Configuration object differ * from the values in the corresponding variables. If they differ, it will either overwrite the variables if the Configuration * object is marked as changed (e.g. if it was changed with the ConfigGui) or otherwise overwrite the Configuration object's values. @@ -152,11 +163,11 @@ public class ConfigManager try { Class cls = Class.forName(targ.getClassName(), true, mcl); - + if (MOD_CONFIG_CLASSES.get(modid) == null) MOD_CONFIG_CLASSES.put(modid, Sets.>newHashSet()); MOD_CONFIG_CLASSES.get(modid).add(cls); - + String name = (String)targ.getAnnotationInfo().get("name"); if (name == null) name = modid; @@ -188,7 +199,7 @@ public class ConfigManager } } } - + public static Class[] getModConfigClasses(String modid) { return MOD_CONFIG_CLASSES.get(modid).toArray(new Class[0]); @@ -204,7 +215,7 @@ public class ConfigManager File configFile = new File(configDir, name + ".cfg"); return CONFIGS.get(configFile.getAbsolutePath()); } - + private static void sync(Configuration cfg, Class cls, String modid, String category, boolean loading, Object instance) { for (Field f : cls.getDeclaredFields()) @@ -213,7 +224,7 @@ public class ConfigManager continue; if (Modifier.isStatic(f.getModifiers()) != (instance == null)) continue; - + String comment = null; Comment ca = f.getAnnotation(Comment.class); if (ca != null) @@ -223,7 +234,7 @@ public class ConfigManager LangKey la = f.getAnnotation(LangKey.class); if (la != null) langKey = la.value(); - + boolean requiresMcRestart = f.isAnnotationPresent(Config.RequiresMcRestart.class); boolean requiresWorldRestart = f.isAnnotationPresent(Config.RequiresWorldRestart.class); @@ -236,16 +247,16 @@ public class ConfigManager IFieldWrapper wrapper = FieldWrapper.get(instance, f, category); ITypeAdapter adapt = wrapper.getTypeAdapter(); Property.Type propType = adapt.getType(); - + for (String key : wrapper.getKeys()) { String suffix = key.replaceFirst(wrapper.getCategory() + ".", ""); - + boolean existed = exists(cfg, wrapper.getCategory(), suffix); if (!existed || loading) //Creates keys in category specified by the wrapper if new ones are programaticaly added { Property property = property(cfg, wrapper.getCategory(), suffix, propType, adapt.isArrayAdapter()); - + adapt.setDefaultValue(property, wrapper.getValue(key)); if (!existed) adapt.setValue(property, wrapper.getValue(key)); @@ -253,7 +264,7 @@ public class ConfigManager wrapper.setValue(key, adapt.getValue(property)); } else //If the key is not new, sync according to shoudlReadFromVar() - { + { Property property = property(cfg, wrapper.getCategory(), suffix, propType, adapt.isArrayAdapter()); Object propVal = adapt.getValue(property); Object mapVal = wrapper.getValue(key); @@ -263,25 +274,25 @@ public class ConfigManager wrapper.setValue(key, propVal); } } - + ConfigCategory confCat = cfg.getCategory(wrapper.getCategory()); - + for (Property property : confCat.getOrderedValues())//Are new keys in the Configuration object? { if (!wrapper.handlesKey(property.getName())) continue; - + if (loading || !wrapper.hasKey(property.getName())) - { + { Object value = wrapper.getTypeAdapter().getValue(property); wrapper.setValue(confCat.getName() + "." + property.getName(), value); } } - - if (loading) //Doing this after the loops. The wrapper should set cosmetic stuff. + + if (loading) //Doing this after the loops. The wrapper should set cosmetic stuff. wrapper.setupConfiguration(cfg, comment, langKey, requiresMcRestart, requiresWorldRestart); - + } catch (Exception e) //If anything goes wrong, add the errored field and class. { @@ -289,9 +300,9 @@ public class ConfigManager String error = String.format(format, f.getName(), cls.getName()); throw new RuntimeException(error, e); } - } + } else if (f.getType().getSuperclass() != null && f.getType().getSuperclass().equals(Object.class)) //Descend the object tree - { + { Object newInstance = null; try { @@ -302,14 +313,14 @@ public class ConfigManager //This should never happen. Previous checks should eliminate this. Throwables.propagate(e); } - + String sub = (category.isEmpty() ? "" : category + ".") + getName(f).toLowerCase(Locale.ENGLISH); ConfigCategory confCat = cfg.getCategory(sub); confCat.setComment(comment); confCat.setLanguageKey(langKey); confCat.setRequiresMcRestart(requiresMcRestart); confCat.setRequiresWorldRestart(requiresWorldRestart); - + sync(cfg, f.getType(), modid, sub, loading, newInstance); } else @@ -323,7 +334,7 @@ public class ConfigManager static final Joiner NEW_LINE = Joiner.on('\n'); static final Joiner PIPE = Joiner.on('|'); - + private static Property property(Configuration cfg, String category, String property, Property.Type type, boolean isList) { Property prop = cfg.getCategory(category).get(property); @@ -337,12 +348,12 @@ public class ConfigManager } return prop; } - + private static boolean exists(Configuration cfg, String category, String property) { return cfg.hasCategory(category) && cfg.getCategory(category).containsKey(property); } - + private static boolean shouldReadFromVar(Property property, Object propValue, Object fieldValue) { if (!propValue.equals(fieldValue)) diff --git a/src/main/java/net/minecraftforge/common/config/FieldWrapper.java b/src/main/java/net/minecraftforge/common/config/FieldWrapper.java index 19272c539..35fcfb424 100644 --- a/src/main/java/net/minecraftforge/common/config/FieldWrapper.java +++ b/src/main/java/net/minecraftforge/common/config/FieldWrapper.java @@ -1,6 +1,7 @@ package net.minecraftforge.common.config; import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Iterator; @@ -67,6 +68,7 @@ public abstract class FieldWrapper implements IFieldWrapper { private Map theMap = null; private Type mType; + ITypeAdapter adapter; @SuppressWarnings("unchecked") private MapWrapper(String category, Field field, Object instance) @@ -90,18 +92,25 @@ public abstract class FieldWrapper implements IFieldWrapper ParameterizedType type = (ParameterizedType) field.getGenericType(); mType = type.getActualTypeArguments()[1]; - if (ADAPTERS.get(mType) == null && !Enum.class.isAssignableFrom((Class) mType)) + this.adapter = ADAPTERS.get(mType); + if (this.adapter == null && mType instanceof GenericArrayType) + { + this.adapter = ADAPTERS.get(ARRAY_REMAP.get(((GenericArrayType)mType).getGenericComponentType())); //J6 seems to have issues, Need to find a better way to translate this. We don't have access to array depth. + } + + if (mType instanceof Class && Enum.class.isAssignableFrom((Class)mType)) + { + this.adapter = TypeAdapters.Str; + } + + if (this.adapter == null) throw new IllegalArgumentException(String.format("The map '%s' of class '%s' has target values which are neither primitive nor an enum!", field.getName(), field.getDeclaringClass().getCanonicalName())); - } @Override public ITypeAdapter getTypeAdapter() { - ITypeAdapter adapter = ADAPTERS.get(mType); - if (adapter == null && Enum.class.isAssignableFrom((Class) mType)) - adapter = TypeAdapters.Str; return adapter; } diff --git a/src/test/java/net/minecraftforge/debug/ConfigTest.java b/src/test/java/net/minecraftforge/debug/ConfigTest.java index db6f5c1c6..fcd6c5a97 100644 --- a/src/test/java/net/minecraftforge/debug/ConfigTest.java +++ b/src/test/java/net/minecraftforge/debug/ConfigTest.java @@ -25,12 +25,12 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class ConfigTest { public static final String MODID = "config_test"; - + @Mod.EventHandler public void preInit(FMLPreInitializationEvent event) { MinecraftForge.EVENT_BUS.register(this); } - + @Mod.EventHandler public void init(FMLInitializationEvent event) { System.out.println("Old: " + CONFIG_TYPES.bool); @@ -39,7 +39,7 @@ public class ConfigTest ConfigManager.sync(MODID, Type.INSTANCE); System.out.println("After sync: " + CONFIG_TYPES.bool); } - + @SubscribeEvent public void onConfigChangedEvent(OnConfigChangedEvent event) { if (event.getModID().equals(MODID)) @@ -134,7 +134,7 @@ public class ConfigTest } } } - + @LangKey("config_test.config.maps") @Config(modid = MODID, name = MODID + "_map") public static class CONFIG_MAP @@ -142,8 +142,8 @@ public class ConfigTest @Name("map") @RequiresMcRestart public static Map theMap; - - static + + static { theMap = Maps.newHashMap(); for (int i = 0; i < 7; i++)