From 5cce0545482fb7f2174d21b9c007c0ae037d44d1 Mon Sep 17 00:00:00 2001 From: LexManos Date: Thu, 23 Feb 2017 17:06:06 -0800 Subject: [PATCH] Add @Name annotation to config system allowing you to use custom key for value. Also added category option to root config to allow customization. See examples/docs for information. --- .../minecraftforge/common/config/Config.java | 63 ++++++++++------- .../common/config/ConfigManager.java | 29 ++++++-- .../common/config/TypeAdapters.java | 67 ++++++++++--------- .../net/minecraftforge/debug/ConfigTest.java | 20 ++++++ 4 files changed, 118 insertions(+), 61 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/config/Config.java b/src/main/java/net/minecraftforge/common/config/Config.java index 2f2ed854e0..35ba80c116 100644 --- a/src/main/java/net/minecraftforge/common/config/Config.java +++ b/src/main/java/net/minecraftforge/common/config/Config.java @@ -28,9 +28,9 @@ import java.lang.annotation.Target; @Target(ElementType.TYPE) public @interface Config { - /** - * The mod id that this configuration is associated with. - */ + /** + * The mod id that this configuration is associated with. + */ String modid(); /** * A user friendly name for the config file, @@ -45,47 +45,60 @@ public @interface Config */ Type type() default Type.INSTANCE; + /** + * Root element category, defaults to "general", if this is an empty string then the root category is disabled. + * Any primitive fields will cause an error, and you must specify sub-category objects + */ + String category() default "general"; + public static enum Type { - /** - * Loaded once, directly after mod construction. Before pre-init. - * This class must have static fields. - */ - INSTANCE(true); + /** + * Loaded once, directly after mod construction. Before pre-init. + * This class must have static fields. + */ + INSTANCE(true); - private boolean isStatic = true; - private Type(boolean isStatic) { this.isStatic = isStatic; } - public boolean isStatic(){ return this.isStatic; } + private boolean isStatic = true; + private Type(boolean isStatic) { this.isStatic = isStatic; } + public boolean isStatic(){ return this.isStatic; } } - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) public @interface LangKey { - String value(); + String value(); } - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) public @interface Comment { - String[] value(); + String[] value(); } - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) public @interface RangeInt { - int min() default Integer.MIN_VALUE; - int max() default Integer.MAX_VALUE; + int min() default Integer.MIN_VALUE; + int max() default Integer.MAX_VALUE; } - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) public @interface RangeDouble { - double min() default Double.MIN_VALUE; - double max() default Double.MAX_VALUE; + double min() default Double.MIN_VALUE; + double max() default Double.MAX_VALUE; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface Name + { + String value(); } } diff --git a/src/main/java/net/minecraftforge/common/config/ConfigManager.java b/src/main/java/net/minecraftforge/common/config/ConfigManager.java index 393ab85f0f..50352df05f 100644 --- a/src/main/java/net/minecraftforge/common/config/ConfigManager.java +++ b/src/main/java/net/minecraftforge/common/config/ConfigManager.java @@ -40,6 +40,7 @@ import com.google.common.collect.Multimap; import net.minecraftforge.common.config.Config.Comment; import net.minecraftforge.common.config.Config.LangKey; +import net.minecraftforge.common.config.Config.Name; import net.minecraftforge.common.config.Config.RangeDouble; import net.minecraftforge.common.config.Config.RangeInt; import net.minecraftforge.fml.common.FMLLog; @@ -134,6 +135,10 @@ public class ConfigManager String name = (String)targ.getAnnotationInfo().get("name"); if (name == null) name = modid; + String category = (String)targ.getAnnotationInfo().get("category"); + if (category == null) + category = "general"; + File file = new File(configDir, name + ".cfg"); Configuration cfg = CONFIGS.get(file.getAbsolutePath()); @@ -144,7 +149,7 @@ public class ConfigManager CONFIGS.put(file.getAbsolutePath(), cfg); } - createConfig(cfg, cls, modid, type == Config.Type.INSTANCE); + createConfig(cfg, cls, modid, type == Config.Type.INSTANCE, category); cfg.save(); @@ -160,9 +165,8 @@ public class ConfigManager // ======================================================= // INTERNAL // ======================================================= - private static void createConfig(Configuration cfg, Class cls, String modid, boolean isStatic) + private static void createConfig(Configuration cfg, Class cls, String modid, boolean isStatic, String category) { - String category = "general"; for (Field f : cls.getDeclaredFields()) { if (!Modifier.isPublic(f.getModifiers())) @@ -196,19 +200,25 @@ public class ConfigManager if (adapter != null) { + if (category.isEmpty()) + throw new RuntimeException("Can not specify a primitive field when the category is empty: " + f.getDeclaringClass() +"/" + f.getName()); prop = adapter.getProp(cfg, category, f, instance, comment); set(instance, f, adapter.getValue(prop)); } else if (ftype.getSuperclass() == Enum.class) { + if (category.isEmpty()) + throw new RuntimeException("Can not specify a primitive field when the category is empty: " + f.getDeclaringClass() +"/" + f.getName()); Enum enu = (Enum)get(instance, f); - prop = cfg.get(category, f.getName(), enu.name(), comment); + prop = cfg.get(category, getName(f), enu.name(), comment); prop.setValidationPattern(makePattern((Class)ftype)); set(instance, f, Enum.valueOf((Class)ftype, prop.getString())); } else if (ftype == Map.class) { - String sub = category + "." + f.getName().toLowerCase(Locale.ENGLISH); + if (category.isEmpty()) + throw new RuntimeException("Can not specify a primitive field when the category is empty: " + f.getDeclaringClass() +"/" + f.getName()); + String sub = category + "." + getName(f).toLowerCase(Locale.ENGLISH); Map m = (Map)get(instance, f); ParameterizedType type = (ParameterizedType)f.getGenericType(); Type mtype = type.getActualTypeArguments()[1]; @@ -238,7 +248,7 @@ public class ConfigManager } else if (ftype.getSuperclass() == Object.class) //Only support classes that are one level below Object. { - String sub = category + "." + f.getName().toLowerCase(Locale.ENGLISH); + String sub = (category.isEmpty() ? "" : category + ".") + getName(f).toLowerCase(Locale.ENGLISH); Object sinst = get(instance, f); for (Field sf : ftype.getDeclaredFields()) { @@ -306,4 +316,11 @@ public class ConfigManager return Pattern.compile(PIPE.join(lst)); } + private static String getName(Field f) + { + if (f.isAnnotationPresent(Name.class)) + return f.getAnnotation(Name.class).value(); + return f.getName(); + } + } diff --git a/src/main/java/net/minecraftforge/common/config/TypeAdapters.java b/src/main/java/net/minecraftforge/common/config/TypeAdapters.java index 047e7226a4..318183a26c 100644 --- a/src/main/java/net/minecraftforge/common/config/TypeAdapters.java +++ b/src/main/java/net/minecraftforge/common/config/TypeAdapters.java @@ -46,7 +46,7 @@ class TypeAdapters */ static ITypeAdapter bool = new TypeAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), getBoolean(instance, field), comment); + return cfg.get(category, getName(field), getBoolean(instance, field), comment); } public Object getValue(Property prop) { return prop.getBoolean(); @@ -54,7 +54,7 @@ class TypeAdapters }; static ITypeAdapter boolA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (boolean[])getObject(instance, field), comment); + return cfg.get(category, getName(field), (boolean[])getObject(instance, field), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (boolean[])value, null); @@ -65,7 +65,7 @@ class TypeAdapters }; static ITypeAdapter Bool = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (Boolean)getObject(instance, field), comment); + return cfg.get(category, getName(field), (Boolean)getObject(instance, field), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (Boolean)value, null); @@ -76,7 +76,7 @@ class TypeAdapters }; static ITypeAdapter BoolA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Booleans.toArray(Arrays.asList((Boolean[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Booleans.toArray(Arrays.asList((Boolean[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (Boolean)value, null); @@ -87,7 +87,7 @@ class TypeAdapters }; static ITypeAdapter flt = new TypeAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), getFloat(instance, field), comment); + return cfg.get(category, getName(field), getFloat(instance, field), comment); } public Object getValue(Property prop) { return (float)prop.getDouble(); @@ -95,7 +95,7 @@ class TypeAdapters }; static ITypeAdapter fltA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Doubles.toArray(Floats.asList((float[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Doubles.toArray(Floats.asList((float[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, Doubles.toArray(Floats.asList((float[])value)), null); @@ -106,7 +106,7 @@ class TypeAdapters }; static ITypeAdapter Flt = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (Float)getObject(instance, field), comment); + return cfg.get(category, getName(field), (Float)getObject(instance, field), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (Float)value, null); @@ -117,7 +117,7 @@ class TypeAdapters }; static ITypeAdapter FltA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Doubles.toArray(Arrays.asList((Float[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Doubles.toArray(Arrays.asList((Float[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, Doubles.toArray(Arrays.asList((Float[])value)), null); @@ -128,7 +128,7 @@ class TypeAdapters }; static ITypeAdapter dbl = new TypeAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), getDouble(instance, field), comment); + return cfg.get(category, getName(field), getDouble(instance, field), comment); } public Object getValue(Property prop) { return prop.getDouble(); @@ -136,7 +136,7 @@ class TypeAdapters }; static ITypeAdapter dblA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (double[])getObject(instance, field), comment); + return cfg.get(category, getName(field), (double[])getObject(instance, field), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (double[])value, null); @@ -147,7 +147,7 @@ class TypeAdapters }; static ITypeAdapter Dbl = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (Double)getObject(instance, field), comment); + return cfg.get(category, getName(field), (Double)getObject(instance, field), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (Double)value, null); @@ -158,7 +158,7 @@ class TypeAdapters }; static ITypeAdapter DblA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Doubles.toArray(Arrays.asList((Double[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Doubles.toArray(Arrays.asList((Double[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, Doubles.toArray(Arrays.asList((Double[])value)), null); @@ -169,7 +169,7 @@ class TypeAdapters }; static ITypeAdapter byt = new TypeAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), getByte(instance, field), comment, Byte.MIN_VALUE, Byte.MAX_VALUE); + return cfg.get(category, getName(field), getByte(instance, field), comment, Byte.MIN_VALUE, Byte.MAX_VALUE); } public Object getValue(Property prop) { return (byte)prop.getInt(); @@ -177,7 +177,7 @@ class TypeAdapters }; static ITypeAdapter bytA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Ints.toArray(Bytes.asList((byte[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Ints.toArray(Bytes.asList((byte[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, Ints.toArray(Bytes.asList((byte[])value)), null); @@ -188,7 +188,7 @@ class TypeAdapters }; static ITypeAdapter Byt = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (Byte)getObject(instance, field), comment, Byte.MIN_VALUE, Byte.MAX_VALUE); + return cfg.get(category, getName(field), (Byte)getObject(instance, field), comment, Byte.MIN_VALUE, Byte.MAX_VALUE); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (Byte)value, null, Byte.MIN_VALUE, Byte.MAX_VALUE); @@ -199,7 +199,7 @@ class TypeAdapters }; static ITypeAdapter BytA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Ints.toArray(Arrays.asList((Byte[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Ints.toArray(Arrays.asList((Byte[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, Ints.toArray(Arrays.asList((Byte[])value)), null); @@ -210,7 +210,7 @@ class TypeAdapters }; static ITypeAdapter chr = new TypeAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), getChar(instance, field), comment, Character.MIN_VALUE, Character.MAX_VALUE); + return cfg.get(category, getName(field), getChar(instance, field), comment, Character.MIN_VALUE, Character.MAX_VALUE); } public Object getValue(Property prop) { return (char)prop.getInt(); @@ -225,7 +225,7 @@ class TypeAdapters return ret; } public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), toPrim((char[])getObject(instance, field)), comment); + return cfg.get(category, getName(field), toPrim((char[])getObject(instance, field)), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, toPrim((char[])value), null); @@ -240,7 +240,7 @@ class TypeAdapters }; static ITypeAdapter Chr = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (Character)getObject(instance, field), comment, Character.MIN_VALUE, Character.MAX_VALUE); + return cfg.get(category, getName(field), (Character)getObject(instance, field), comment, Character.MIN_VALUE, Character.MAX_VALUE); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (Character)value, null, Character.MIN_VALUE, Character.MAX_VALUE); @@ -258,7 +258,7 @@ class TypeAdapters return ret; } public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), toPrim((Character[])getObject(instance, field)), comment); + return cfg.get(category, getName(field), toPrim((Character[])getObject(instance, field)), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, toPrim((Character[])value), null); @@ -273,7 +273,7 @@ class TypeAdapters }; static ITypeAdapter shrt = new TypeAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), getShort(instance, field), comment, Short.MIN_VALUE, Short.MAX_VALUE); + return cfg.get(category, getName(field), getShort(instance, field), comment, Short.MIN_VALUE, Short.MAX_VALUE); } public Object getValue(Property prop) { return (short)prop.getInt(); @@ -281,7 +281,7 @@ class TypeAdapters }; static ITypeAdapter shrtA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Ints.toArray(Shorts.asList((short[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Ints.toArray(Shorts.asList((short[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, Ints.toArray(Shorts.asList((short[])value)), null); @@ -292,7 +292,7 @@ class TypeAdapters }; static ITypeAdapter Shrt = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (Short)getObject(instance, field), comment, Short.MIN_VALUE, Short.MAX_VALUE); + return cfg.get(category, getName(field), (Short)getObject(instance, field), comment, Short.MIN_VALUE, Short.MAX_VALUE); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (Short)value, null, Short.MIN_VALUE, Short.MAX_VALUE); @@ -303,7 +303,7 @@ class TypeAdapters }; static ITypeAdapter ShrtA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Ints.toArray(Arrays.asList((Short[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Ints.toArray(Arrays.asList((Short[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, Ints.toArray(Arrays.asList((Short[])value)), null); @@ -318,7 +318,7 @@ class TypeAdapters }; static ITypeAdapter int_ = new TypeAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), getInt(instance, field), comment, Integer.MIN_VALUE, Integer.MAX_VALUE); + return cfg.get(category, getName(field), getInt(instance, field), comment, Integer.MIN_VALUE, Integer.MAX_VALUE); } public Object getValue(Property prop) { return prop.getInt(); @@ -326,7 +326,7 @@ class TypeAdapters }; static ITypeAdapter intA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (int[])getObject(instance, field), comment); + return cfg.get(category, getName(field), (int[])getObject(instance, field), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (int[])value, null); @@ -337,7 +337,7 @@ class TypeAdapters }; static ITypeAdapter Int = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (Integer)getObject(instance, field), comment, Integer.MIN_VALUE, Integer.MAX_VALUE); + return cfg.get(category, getName(field), (Integer)getObject(instance, field), comment, Integer.MIN_VALUE, Integer.MAX_VALUE); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (Integer)value, null, Integer.MIN_VALUE, Integer.MAX_VALUE); @@ -348,7 +348,7 @@ class TypeAdapters }; static ITypeAdapter IntA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), Ints.toArray(Arrays.asList((Integer[])getObject(instance, field))), comment); + return cfg.get(category, getName(field), Ints.toArray(Arrays.asList((Integer[])getObject(instance, field))), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, Ints.toArray(Arrays.asList((Integer[])value)), null); @@ -359,7 +359,7 @@ class TypeAdapters }; static ITypeAdapter.Map Str = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (String)getObject(instance, field), comment); + return cfg.get(category, getName(field), (String)getObject(instance, field), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (String)value, null); @@ -370,7 +370,7 @@ class TypeAdapters }; static ITypeAdapter StrA = new MapAdapter() { public Property getProp(Configuration cfg, String category, Field field, Object instance, String comment) { - return cfg.get(category, field.getName(), (String[])getObject(instance, field), comment); + return cfg.get(category, getName(field), (String[])getObject(instance, field), comment); } public Property getProp(Configuration cfg, String category, String name, Object value) { return cfg.get(category, name, (String[])value, null); @@ -455,6 +455,13 @@ class TypeAdapters } return 0; } + + public String getName(Field f) + { + if (f.isAnnotationPresent(Config.Name.class)) + return f.getAnnotation(Config.Name.class).value(); + return f.getName(); + } } private static abstract class MapAdapter extends TypeAdapter implements ITypeAdapter.Map {} } diff --git a/src/test/java/net/minecraftforge/debug/ConfigTest.java b/src/test/java/net/minecraftforge/debug/ConfigTest.java index 3978d5ba7d..5d73c1159f 100644 --- a/src/test/java/net/minecraftforge/debug/ConfigTest.java +++ b/src/test/java/net/minecraftforge/debug/ConfigTest.java @@ -71,4 +71,24 @@ public class ConfigTest @Comment({"This is a really long", "Multi-line comment"}) public static String Comments = "Hi Tv!"; } + @Config(modid = MODID, name = MODID + "_subcats", category = "") + public static class CONFIG_SUBCATS + { + //public static String THIS_WILL_ERROR = "DUH"; + + @Name("test_a") + public static SubCat sub1 = new SubCat("Hello"); + @Name("test_b") + public static SubCat sub2 = new SubCat("Goodbye"); + + public static class SubCat + { + @Name("i_say") + public static String value; + public SubCat(String value) + { + this.value = value; + } + } + } }