Skip to content

Commit ad8ba17

Browse files
committed
some more config fixes
1 parent 9810a5c commit ad8ba17

File tree

3 files changed

+218
-33
lines changed

3 files changed

+218
-33
lines changed

src/main/java/com/falsepattern/lib/config/Config.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,7 @@
1515
String modid();
1616

1717
/**
18-
* A user friendly name for the config file,
19-
* the default will be modid
20-
*/
21-
String name() default "";
22-
23-
/**
24-
* Root element category, defaults to "general", if this is an empty string then the root category is disabled.
25-
* Any primitive fields will cause an error, and you must specify sub-category objects
18+
* Root element category, defaults to "general". You must not specify an empty string.
2619
*/
2720
String category() default "general";
2821

src/main/java/com/falsepattern/lib/config/ConfigurationManager.java

Lines changed: 61 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
import com.falsepattern.lib.StableAPI;
44
import com.falsepattern.lib.internal.CoreLoadingPlugin;
55
import com.falsepattern.lib.internal.FalsePatternLib;
6+
import cpw.mods.fml.client.config.IConfigElement;
67
import cpw.mods.fml.client.event.ConfigChangedEvent;
8+
import cpw.mods.fml.common.FMLCommonHandler;
79
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
810
import lombok.*;
911
import net.minecraftforge.common.MinecraftForge;
12+
import net.minecraftforge.common.config.ConfigElement;
1013
import net.minecraftforge.common.config.Configuration;
1114

1215
import java.lang.reflect.Field;
@@ -22,7 +25,9 @@
2225
@NoArgsConstructor(access = AccessLevel.PRIVATE)
2326
@StableAPI(since = "0.6.0")
2427
public 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
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package com.falsepattern.lib.config;
2+
3+
import cpw.mods.fml.client.config.ConfigGuiType;
4+
import cpw.mods.fml.client.config.GuiConfigEntries;
5+
import cpw.mods.fml.client.config.GuiEditArrayEntries;
6+
import cpw.mods.fml.client.config.IConfigElement;
7+
8+
import java.util.List;
9+
import java.util.regex.Pattern;
10+
11+
public class IConfigElementProxy<T> implements IConfigElement<T> {
12+
private final IConfigElement<T> proxied;
13+
private final Runnable onUpdate;
14+
public IConfigElementProxy(IConfigElement<T> proxied, Runnable onUpdate) {
15+
this.proxied = proxied;
16+
this.onUpdate = onUpdate;
17+
}
18+
19+
@Override
20+
public boolean isProperty() {
21+
return proxied.isProperty();
22+
}
23+
24+
@Override
25+
public Class<? extends GuiConfigEntries.IConfigEntry> getConfigEntryClass() {
26+
return proxied.getConfigEntryClass();
27+
}
28+
29+
@Override
30+
public Class<? extends GuiEditArrayEntries.IArrayEntry> getArrayEntryClass() {
31+
return proxied.getArrayEntryClass();
32+
}
33+
34+
@Override
35+
public String getName() {
36+
return proxied.getName();
37+
}
38+
39+
@Override
40+
public String getQualifiedName() {
41+
return proxied.getQualifiedName();
42+
}
43+
44+
@Override
45+
public String getLanguageKey() {
46+
return proxied.getLanguageKey();
47+
}
48+
49+
@Override
50+
public String getComment() {
51+
return proxied.getComment();
52+
}
53+
54+
@SuppressWarnings("rawtypes")
55+
@Override
56+
public List<IConfigElement> getChildElements() {
57+
return proxied.getChildElements();
58+
}
59+
60+
@Override
61+
public ConfigGuiType getType() {
62+
return proxied.getType();
63+
}
64+
65+
@Override
66+
public boolean isList() {
67+
return proxied.isList();
68+
}
69+
70+
@Override
71+
public boolean isListLengthFixed() {
72+
return proxied.isListLengthFixed();
73+
}
74+
75+
@Override
76+
public int getMaxListLength() {
77+
return proxied.getMaxListLength();
78+
}
79+
80+
@Override
81+
public boolean isDefault() {
82+
return proxied.isDefault();
83+
}
84+
85+
@Override
86+
public Object getDefault() {
87+
return proxied.getDefault();
88+
}
89+
90+
@Override
91+
public Object[] getDefaults() {
92+
return proxied.getDefaults();
93+
}
94+
95+
@Override
96+
public void setToDefault() {
97+
proxied.setToDefault();
98+
}
99+
100+
@Override
101+
public boolean requiresWorldRestart() {
102+
return proxied.requiresWorldRestart();
103+
}
104+
105+
@Override
106+
public boolean showInGui() {
107+
return proxied.showInGui();
108+
}
109+
110+
@Override
111+
public boolean requiresMcRestart() {
112+
return proxied.requiresMcRestart();
113+
}
114+
115+
@Override
116+
public Object get() {
117+
return proxied.get();
118+
}
119+
120+
@Override
121+
public Object[] getList() {
122+
return proxied.getList();
123+
}
124+
125+
@Override
126+
public void set(T value) {
127+
proxied.set(value);
128+
onUpdate.run();
129+
}
130+
131+
@Override
132+
public void set(T[] aVal) {
133+
proxied.set(aVal);
134+
onUpdate.run();
135+
}
136+
137+
@Override
138+
public String[] getValidValues() {
139+
return proxied.getValidValues();
140+
}
141+
142+
@Override
143+
public T getMinValue() {
144+
return proxied.getMinValue();
145+
}
146+
147+
@Override
148+
public T getMaxValue() {
149+
return proxied.getMaxValue();
150+
}
151+
152+
@Override
153+
public Pattern getValidationPattern() {
154+
return proxied.getValidationPattern();
155+
}
156+
}

0 commit comments

Comments
 (0)