Skip to content

Commit 1737345

Browse files
committed
internalize ConfigurationManager and DependencyLoader internal logic
1 parent 3a1b2ba commit 1737345

File tree

5 files changed

+513
-488
lines changed

5 files changed

+513
-488
lines changed
Lines changed: 7 additions & 232 deletions
Original file line numberDiff line numberDiff line change
@@ -1,189 +1,28 @@
11
package com.falsepattern.lib.config;
22

33
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+
68
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;
109

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;
1710
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;
3111

3212
/**
3313
* Class for controlling the loading of configuration files.
3414
*/
3515
@NoArgsConstructor(access = AccessLevel.PRIVATE)
3616
@StableAPI(since = "0.6.0")
3717
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;
4718

4819
/**
4920
* Registers a configuration class to be loaded. This should be done in preInit.
5021
*
5122
* @param configClass The class to register.
5223
*/
5324
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 + "\nPossible 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);
18726
}
18827

18928
/**
@@ -193,72 +32,8 @@ private static Object extractValue(Field field) {
19332
*
19433
* @return The configuration elements.
19534
*/
196-
@SuppressWarnings({"rawtypes", "unchecked"})
35+
@SuppressWarnings("rawtypes")
19736
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);
26338
}
26439
}

0 commit comments

Comments
 (0)