1
1
package com .falsepattern .lib .config ;
2
2
3
3
import com .falsepattern .lib .StableAPI ;
4
- import com .falsepattern .lib .internal .FalsePatternLib ;
5
- import com .falsepattern .lib .util .FileUtil ;
4
+ import com .falsepattern .lib .internal .impl .config .ConfigurationManagerImpl ;
5
+ import lombok .AccessLevel ;
6
+ import lombok .NoArgsConstructor ;
7
+
6
8
import cpw .mods .fml .client .config .IConfigElement ;
7
- import cpw .mods .fml .client .event .ConfigChangedEvent ;
8
- import cpw .mods .fml .common .FMLCommonHandler ;
9
- import cpw .mods .fml .common .eventhandler .SubscribeEvent ;
10
9
11
- import java .lang .reflect .Field ;
12
- import java .lang .reflect .InvocationTargetException ;
13
- import java .nio .file .Path ;
14
- import java .util .Arrays ;
15
- import java .util .HashMap ;
16
- import java .util .HashSet ;
17
10
import java .util .List ;
18
- import java .util .Map ;
19
- import java .util .Optional ;
20
- import java .util .Set ;
21
- import java .util .regex .Pattern ;
22
- import java .util .stream .Collectors ;
23
- import lombok .AccessLevel ;
24
- import lombok .NoArgsConstructor ;
25
- import lombok .SneakyThrows ;
26
- import lombok .val ;
27
- import lombok .var ;
28
- import net .minecraft .launchwrapper .Launch ;
29
- import net .minecraftforge .common .config .ConfigElement ;
30
- import net .minecraftforge .common .config .Configuration ;
31
11
32
12
/**
33
13
* Class for controlling the loading of configuration files.
34
14
*/
35
15
@ NoArgsConstructor (access = AccessLevel .PRIVATE )
36
16
@ StableAPI (since = "0.6.0" )
37
17
public class ConfigurationManager {
38
- private static final Map <String , Configuration > configs = new HashMap <>();
39
-
40
- private static final Map <Configuration , Set <Class <?>>> configToClassMap = new HashMap <>();
41
-
42
- private static final ConfigurationManager instance = new ConfigurationManager ();
43
-
44
- private static boolean initialized = false ;
45
-
46
- private static Path configDir ;
47
18
48
19
/**
49
20
* Registers a configuration class to be loaded. This should be done in preInit.
50
21
*
51
22
* @param configClass The class to register.
52
23
*/
53
24
public static void registerConfig (Class <?> configClass ) throws ConfigException {
54
- init ();
55
- val cfg = Optional .ofNullable (configClass .getAnnotation (Config .class ))
56
- .orElseThrow (() -> new ConfigException (
57
- "Class " + configClass .getName () + " does not have a @Config annotation!" ));
58
- val category = Optional .of (cfg .category ().trim ())
59
- .map ((cat ) -> cat .length () == 0 ? null : cat )
60
- .orElseThrow (() -> new ConfigException (
61
- "Config class " + configClass .getName () + " has an empty category!" ));
62
- val rawConfig = configs .computeIfAbsent (cfg .modid (), (ignored ) -> {
63
- val c = new Configuration (configDir .resolve (cfg .modid () + ".cfg" ).toFile ());
64
- c .load ();
65
- return c ;
66
- });
67
- configToClassMap .computeIfAbsent (rawConfig , (ignored ) -> new HashSet <>()).add (configClass );
68
- try {
69
- processConfigInternal (configClass , category , rawConfig );
70
- rawConfig .save ();
71
- } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | NoSuchFieldException e ) {
72
- throw new ConfigException (e );
73
- }
74
- }
75
-
76
- private static void processConfigInternal (Class <?> configClass , String category , Configuration rawConfig )
77
- throws IllegalAccessException , NoSuchMethodException , InvocationTargetException , NoSuchFieldException ,
78
- ConfigException {
79
- val cat = rawConfig .getCategory (category );
80
- for (val field : configClass .getDeclaredFields ()) {
81
- if (field .getAnnotation (Config .Ignore .class ) != null ) {
82
- continue ;
83
- }
84
- field .setAccessible (true );
85
- val comment = Optional .ofNullable (field .getAnnotation (Config .Comment .class ))
86
- .map (Config .Comment ::value )
87
- .map ((lines ) -> String .join ("\n " , lines ))
88
- .orElse ("" );
89
- val name = Optional .ofNullable (field .getAnnotation (Config .Name .class ))
90
- .map (Config .Name ::value )
91
- .orElse (field .getName ());
92
- val langKey = Optional .ofNullable (field .getAnnotation (Config .LangKey .class ))
93
- .map (Config .LangKey ::value )
94
- .orElse (name );
95
- val fieldClass = field .getType ();
96
- var boxed = false ;
97
- if ((boxed = fieldClass .equals (Boolean .class )) || fieldClass .equals (boolean .class )) {
98
- val defaultValue = Optional .ofNullable (field .getAnnotation (Config .DefaultBoolean .class ))
99
- .map (Config .DefaultBoolean ::value )
100
- .orElse (boxed ? (Boolean ) field .get (null ) : field .getBoolean (null ));
101
- field .setBoolean (null , rawConfig .getBoolean (name , category , defaultValue , comment , langKey ));
102
- } else if ((boxed = fieldClass .equals (Integer .class )) || fieldClass .equals (int .class )) {
103
- val range = Optional .ofNullable (field .getAnnotation (Config .RangeInt .class ));
104
- val min = range .map (Config .RangeInt ::min ).orElse (Integer .MIN_VALUE );
105
- val max = range .map (Config .RangeInt ::max ).orElse (Integer .MAX_VALUE );
106
- val defaultValue = Optional .ofNullable (field .getAnnotation (Config .DefaultInt .class ))
107
- .map (Config .DefaultInt ::value )
108
- .orElse (boxed ? (Integer ) field .get (null ) : field .getInt (null ));
109
- field .setInt (null , rawConfig .getInt (name , category , defaultValue , min , max , comment , langKey ));
110
- } else if ((boxed = fieldClass .equals (Float .class )) || fieldClass .equals (float .class )) {
111
- val range = Optional .ofNullable (field .getAnnotation (Config .RangeFloat .class ));
112
- val min = range .map (Config .RangeFloat ::min ).orElse (Float .MIN_VALUE );
113
- val max = range .map (Config .RangeFloat ::max ).orElse (Float .MAX_VALUE );
114
- val defaultValue = Optional .ofNullable (field .getAnnotation (Config .DefaultFloat .class ))
115
- .map (Config .DefaultFloat ::value )
116
- .orElse (boxed ? (Float ) field .get (null ) : field .getFloat (null ));
117
- field .setFloat (null , rawConfig .getFloat (name , category , defaultValue , min , max , comment , langKey ));
118
- } else if (fieldClass .equals (String .class )) {
119
- val defaultValue = Optional .ofNullable (field .getAnnotation (Config .DefaultString .class ))
120
- .map (Config .DefaultString ::value )
121
- .orElse ((String ) field .get (null ));
122
- val pattern = Optional .ofNullable (field .getAnnotation (Config .Pattern .class ))
123
- .map (Config .Pattern ::value )
124
- .map (Pattern ::compile )
125
- .orElse (null );
126
- field .set (null , rawConfig .getString (name , category , defaultValue , comment , langKey , pattern ));
127
- } else if (fieldClass .isEnum ()) {
128
- val enumValues = Arrays .stream ((Object []) fieldClass .getDeclaredMethod ("values" ).invoke (null ))
129
- .map ((obj ) -> (Enum <?>) obj )
130
- .collect (Collectors .toList ());
131
- val defaultValue = (Enum <?>) Optional .ofNullable (field .getAnnotation (Config .DefaultEnum .class ))
132
- .map (Config .DefaultEnum ::value )
133
- .map ((defName ) -> extractField (fieldClass , defName ))
134
- .map (ConfigurationManager ::extractValue )
135
- .orElse (field .get (null ));
136
- val possibleValues = enumValues .stream ().map (Enum ::name ).toArray (String []::new );
137
- var value = rawConfig .getString (name ,
138
- category ,
139
- defaultValue .name (),
140
- comment + "\n Possible values: " + Arrays .toString (possibleValues ) +
141
- "\n " ,
142
- possibleValues ,
143
- langKey );
144
-
145
- try {
146
- if (!Arrays .asList (possibleValues ).contains (value )) {
147
- throw new NoSuchFieldException ();
148
- }
149
- val enumField = fieldClass .getDeclaredField (value );
150
- if (!enumField .isEnumConstant ()) {
151
- throw new NoSuchFieldException ();
152
- }
153
- field .set (null , enumField .get (null ));
154
- } catch (NoSuchFieldException e ) {
155
- FalsePatternLib .getLog ()
156
- .warn ("Invalid value " + value + " for enum configuration field " + field .getName () +
157
- " of type " + fieldClass .getName () + " in config class " +
158
- configClass .getName () + "! Using default value of " + defaultValue + "!" );
159
- field .set (null , defaultValue );
160
- }
161
- } else if (fieldClass .isArray () && fieldClass .getComponentType ().equals (String .class )) {
162
- val defaultValue = Optional .ofNullable (field .getAnnotation (Config .DefaultStringList .class )).map (Config .DefaultStringList ::value ).orElse ((String [])field .get (null ));
163
- var value = rawConfig .getStringList (name , category , defaultValue , comment , null , langKey );
164
- field .set (null , value );
165
- } else {
166
- throw new ConfigException ("Illegal config field: " + field .getName () + " in " + configClass .getName () +
167
- ": Unsupported type " + fieldClass .getName () +
168
- "! Did you forget an @Ignore annotation?" );
169
- }
170
- if (field .isAnnotationPresent (Config .RequiresMcRestart .class )) {
171
- cat .setRequiresMcRestart (true );
172
- }
173
- if (field .isAnnotationPresent (Config .RequiresWorldRestart .class )) {
174
- cat .setRequiresWorldRestart (true );
175
- }
176
- }
177
- }
178
-
179
- @ SneakyThrows
180
- private static Field extractField (Class <?> clazz , String field ) {
181
- return clazz .getDeclaredField (field );
182
- }
183
-
184
- @ SneakyThrows
185
- private static Object extractValue (Field field ) {
186
- return field .get (null );
25
+ ConfigurationManagerImpl .registerConfig (configClass );
187
26
}
188
27
189
28
/**
@@ -193,72 +32,8 @@ private static Object extractValue(Field field) {
193
32
*
194
33
* @return The configuration elements.
195
34
*/
196
- @ SuppressWarnings ({ "rawtypes" , "unchecked" } )
35
+ @ SuppressWarnings ("rawtypes" )
197
36
public static List <IConfigElement > getConfigElements (Class <?> configClass ) throws ConfigException {
198
- init ();
199
- val cfg = Optional .ofNullable (configClass .getAnnotation (Config .class ))
200
- .orElseThrow (() -> new ConfigException (
201
- "Class " + configClass .getName () + " does not have a @Config annotation!" ));
202
- val rawConfig = Optional .ofNullable (configs .get (cfg .modid ()))
203
- .map ((conf ) -> Optional .ofNullable (configToClassMap .get (conf ))
204
- .map ((l ) -> l .contains (configClass ))
205
- .orElse (false ) ? conf : null )
206
- .orElseThrow (() -> new ConfigException (
207
- "Tried to get config elements for non-registered config class!" ));
208
- val category = cfg .category ();
209
- val elements = new ConfigElement <>(rawConfig .getCategory (category )).getChildElements ();
210
- return elements .stream ().map ((element ) -> new IConfigElementProxy (element , () -> {
211
- try {
212
- processConfigInternal (configClass , category , rawConfig );
213
- rawConfig .save ();
214
- } catch (IllegalAccessException |
215
- NoSuchMethodException |
216
- InvocationTargetException |
217
- NoSuchFieldException |
218
- ConfigException e ) {
219
- e .printStackTrace ();
220
- }
221
- })).collect (Collectors .toList ());
222
- }
223
-
224
- private static void init () {
225
- if (initialized ) {
226
- return ;
227
- }
228
- configDir = FileUtil .getMinecraftHome ().toPath ().resolve ("config" );
229
- initialized = true ;
230
- }
231
-
232
- /**
233
- * Internal, do not use.
234
- */
235
- public static void registerBus () {
236
- FMLCommonHandler .instance ().bus ().register (instance );
237
- }
238
-
239
- /**
240
- * Internal, do not use.
241
- *
242
- * @param event The event.
243
- */
244
- @ SubscribeEvent
245
- public void onConfigChanged (ConfigChangedEvent .OnConfigChangedEvent event ) {
246
- init ();
247
- val config = configs .get (event .modID );
248
- if (config == null ) {
249
- return ;
250
- }
251
- val configClasses = configToClassMap .get (config );
252
- configClasses .forEach ((configClass ) -> {
253
- try {
254
- val category = Optional .ofNullable (configClass .getAnnotation (Config .class ))
255
- .map (Config ::category )
256
- .orElseThrow (() -> new ConfigException (
257
- "Failed to get config category for class " + configClass .getName ()));
258
- processConfigInternal (configClass , category , config );
259
- } catch (Exception e ) {
260
- e .printStackTrace ();
261
- }
262
- });
37
+ return ConfigurationManagerImpl .getConfigElements (configClass );
263
38
}
264
39
}
0 commit comments