33import com .falsepattern .lib .StableAPI ;
44import com .falsepattern .lib .internal .CoreLoadingPlugin ;
55import com .falsepattern .lib .internal .FalsePatternLib ;
6+ import cpw .mods .fml .client .config .IConfigElement ;
67import cpw .mods .fml .client .event .ConfigChangedEvent ;
8+ import cpw .mods .fml .common .FMLCommonHandler ;
79import cpw .mods .fml .common .eventhandler .SubscribeEvent ;
810import lombok .*;
911import net .minecraftforge .common .MinecraftForge ;
12+ import net .minecraftforge .common .config .ConfigElement ;
1013import net .minecraftforge .common .config .Configuration ;
1114
1215import java .lang .reflect .Field ;
2225@ NoArgsConstructor (access = AccessLevel .PRIVATE )
2326@ StableAPI (since = "0.6.0" )
2427public class ConfigurationManager {
25- private static final Map <String , Set <Class <?>>> configs = new HashMap <>();
28+ private static final Map <String , Configuration > configs = new HashMap <>();
29+
30+ private static final Map <Configuration , Set <Class <?>>> configToClassMap = new HashMap <>();
2631
2732 private static final ConfigurationManager instance = new ConfigurationManager ();
2833
@@ -31,27 +36,66 @@ public class ConfigurationManager {
3136 private static Path configDir ;
3237
3338 /**
34- * Registers a configuration class to be loaded.
35- * @param config The class to register.
39+ * Registers a configuration class to be loaded. This should be done in preInit.
40+ * @param configClass The class to register.
3641 */
37- public static void registerConfig (Class <?> config ) throws ConfigException {
38- val cfg = Optional .ofNullable (config .getAnnotation (Config .class )).orElseThrow (() -> new ConfigException ("Class " + config .getName () + " does not have a @Config annotation!" ));
39- val cfgSet = configs .computeIfAbsent (cfg .modid (), (ignored ) -> new HashSet <>());
40- cfgSet .add (config );
42+ public static void registerConfig (Class <?> configClass ) throws ConfigException {
43+ val cfg = Optional
44+ .ofNullable (configClass .getAnnotation (Config .class ))
45+ .orElseThrow (() -> new ConfigException ("Class " + configClass .getName () + " does not have a @Config annotation!" ));
46+ val category = Optional
47+ .of (cfg .category ().trim ())
48+ .map ((cat ) -> cat .length () == 0 ? null : cat )
49+ .orElseThrow (() -> new ConfigException ("Config class " + configClass .getName () + " has an empty category!" ));
50+ val rawConfig = configs .computeIfAbsent (cfg .modid (), (ignored ) -> {
51+ val c = new Configuration (configDir .resolve (cfg .modid () + ".cfg" ).toFile ());
52+ c .load ();
53+ return c ;
54+ });
55+ configToClassMap .computeIfAbsent (rawConfig , (ignored ) -> new HashSet <>()).add (configClass );
4156 try {
42- processConfig (config );
57+ processConfigInternal (configClass , category , rawConfig );
58+ rawConfig .save ();
4359 } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | NoSuchFieldException e ) {
4460 throw new ConfigException (e );
4561 }
4662 }
4763
64+ /**
65+ * Process the configuration into a list of config elements usable in config GUI code.
66+ * @param configClass The class to process.
67+ * @return The configuration elements.
68+ */
69+ public static List <? extends IConfigElement <?>> getConfigElements (Class <?> configClass ) throws ConfigException {
70+ val cfg = Optional
71+ .ofNullable (configClass .getAnnotation (Config .class ))
72+ .orElseThrow (() -> new ConfigException ("Class " + configClass .getName () + " does not have a @Config annotation!" ));
73+ val rawConfig = Optional
74+ .ofNullable (configs .get (cfg .modid ()))
75+ .map ((conf ) -> Optional .ofNullable (configToClassMap .get (conf ))
76+ .map ((l ) -> l .contains (configClass ))
77+ .orElse (false ) ? conf : null )
78+ .orElseThrow (() -> new ConfigException ("Tried to get config elements for non-registed config class!" ));
79+ val category = cfg .category ();
80+ val elements = new ConfigElement <>(rawConfig .getCategory (category )).getChildElements ();
81+ return elements .stream ().map ((element ) -> new IConfigElementProxy <>((IConfigElement <?>) element , () -> {
82+ try {
83+ processConfigInternal (configClass , category , rawConfig );
84+ rawConfig .save ();
85+ } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException |
86+ NoSuchFieldException | ConfigException e ) {
87+ e .printStackTrace ();
88+ }
89+ })).collect (Collectors .toList ());
90+ }
91+
4892 /**
4993 * Internal, do not use.
5094 */
5195 public static void init () {
5296 if (initialized ) return ;
5397 configDir = CoreLoadingPlugin .mcDir .toPath ().resolve ("config" );
54- MinecraftForge . EVENT_BUS .register (instance );
98+ FMLCommonHandler . instance (). bus () .register (instance );
5599 initialized = true ;
56100 }
57101
@@ -61,27 +105,20 @@ public static void init() {
61105 */
62106 @ SubscribeEvent
63107 public void onConfigChanged (ConfigChangedEvent .OnConfigChangedEvent event ) {
64- val configClasses = configs .get (event .modID );
65- if (configClasses == null )
108+ val config = configs .get (event .modID );
109+ if (config == null )
66110 return ;
67- configClasses .forEach ((config ) -> {
111+ val configClasses = configToClassMap .get (config );
112+ configClasses .forEach ((configClass ) -> {
68113 try {
69- processConfig (config );
114+ val category = Optional .ofNullable (configClass .getAnnotation (Config .class )).map (Config ::category ).orElseThrow (() -> new ConfigException ("Failed to get config category for class " + configClass .getName ()));
115+ processConfigInternal (configClass , category , config );
70116 } catch (Exception e ) {
71- throw new RuntimeException ( e );
117+ e . printStackTrace ( );
72118 }
73119 });
74120 }
75-
76- private static void processConfig (Class <?> configClass ) throws IllegalAccessException , NoSuchMethodException , InvocationTargetException , NoSuchFieldException , ConfigException {
77- val cfg = configClass .getAnnotation (Config .class );
78- val category = cfg .category ();
79- var configName = cfg .name ().trim ();
80- if (configName .length () == 0 ) {
81- configName = cfg .modid ();
82- }
83- val rawConfig = new Configuration (configDir .resolve (configName + ".cfg" ).toFile ());
84- rawConfig .load ();
121+ private static void processConfigInternal (Class <?> configClass , String category , Configuration rawConfig ) throws IllegalAccessException , NoSuchMethodException , InvocationTargetException , NoSuchFieldException , ConfigException {
85122 val cat = rawConfig .getCategory (category );
86123 for (val field : configClass .getDeclaredFields ()) {
87124 if (field .getAnnotation (Config .Ignore .class ) != null ) continue ;
@@ -144,7 +181,6 @@ private static void processConfig(Class<?> configClass) throws IllegalAccessExce
144181 cat .setRequiresWorldRestart (true );
145182 }
146183 }
147- rawConfig .save ();
148184 }
149185
150186 @ SneakyThrows
0 commit comments