Skip to content

Commit 016f1ad

Browse files
committed
backport config annotations
1 parent 39fd0d6 commit 016f1ad

File tree

3 files changed

+126
-19
lines changed

3 files changed

+126
-19
lines changed

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

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,6 @@
2525
*/
2626
String category() default "general";
2727

28-
public static enum Type {
29-
/**
30-
* Loaded once, directly after mod construction. Before pre-init.
31-
* This class must have static fields.
32-
*/
33-
INSTANCE(true);
34-
35-
36-
private boolean isStatic = true;
37-
38-
private Type(boolean isStatic) {this.isStatic = isStatic;}
39-
40-
public boolean isStatic() {return this.isStatic;}
41-
}
42-
4328
@Retention(RetentionPolicy.RUNTIME)
4429
@Target({ElementType.FIELD, ElementType.TYPE})
4530
@interface LangKey {
@@ -64,6 +49,12 @@ public static enum Type {
6449
int max() default Integer.MAX_VALUE;
6550
}
6651

52+
@Retention(RetentionPolicy.RUNTIME)
53+
@Target(ElementType.FIELD)
54+
@interface DefaultInt {
55+
int value() default 0;
56+
}
57+
6758
@Retention(RetentionPolicy.RUNTIME)
6859
@Target(ElementType.FIELD)
6960
@interface RangeDouble {
@@ -72,6 +63,12 @@ public static enum Type {
7263
double max() default Double.MAX_VALUE;
7364
}
7465

66+
@Retention(RetentionPolicy.RUNTIME)
67+
@Target(ElementType.FIELD)
68+
@interface DefaultDouble {
69+
double value() default 0d;
70+
}
71+
7572
@Retention(RetentionPolicy.RUNTIME)
7673
@Target(ElementType.FIELD)
7774
@interface Name {
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package com.falsepattern.lib.config;
2+
3+
import cpw.mods.fml.client.event.ConfigChangedEvent;
4+
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
5+
import lombok.AccessLevel;
6+
import lombok.NoArgsConstructor;
7+
import lombok.val;
8+
import lombok.var;
9+
import net.minecraft.launchwrapper.Launch;
10+
import net.minecraftforge.common.MinecraftForge;
11+
import net.minecraftforge.common.config.Configuration;
12+
import net.minecraftforge.common.config.Property;
13+
14+
import java.nio.file.Path;
15+
import java.util.*;
16+
17+
/**
18+
* Class for controlling the loading of configuration files.
19+
*/
20+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
21+
public class ConfigurationManager {
22+
private static final Map<String, Set<Class<?>>> configs = new HashMap<>();
23+
24+
private static final ConfigurationManager instance = new ConfigurationManager();
25+
26+
private static boolean initialized = false;
27+
28+
private static Path configDir;
29+
30+
/**
31+
* Registers a configuration class to be loaded.
32+
* @param config The class to register.
33+
*/
34+
public static void registerConfig(Class<?> config) throws IllegalAccessException {
35+
val cfg = Optional.of(config.getAnnotation(Config.class)).orElseThrow(() -> new IllegalArgumentException("Class " + config.getName() + " does not have a @Config annotation!"));
36+
val cfgSet = configs.computeIfAbsent(cfg.modid(), (ignored) -> new HashSet<>());
37+
cfgSet.add(config);
38+
processConfig(config);
39+
}
40+
41+
/**
42+
* Internal, do not use.
43+
*/
44+
public static void init() {
45+
if (initialized) return;
46+
configDir = Launch.minecraftHome.toPath().resolve("config");
47+
MinecraftForge.EVENT_BUS.register(instance);
48+
initialized = true;
49+
}
50+
51+
/**
52+
* Internal, do not use.
53+
* @param event The event.
54+
*/
55+
@SubscribeEvent
56+
public void onConfigChanged(ConfigChangedEvent.OnConfigChangedEvent event) {
57+
val configClasses = configs.get(event.modID);
58+
if (configClasses == null)
59+
return;
60+
configClasses.forEach((config) -> {
61+
try {
62+
processConfig(config);
63+
} catch (IllegalAccessException e) {
64+
throw new RuntimeException(e);
65+
}
66+
});
67+
}
68+
69+
private static void processConfig(Class<?> configClass) throws IllegalAccessException {
70+
val cfg = configClass.getAnnotation(Config.class);
71+
val category = cfg.category();
72+
val rawConfig = new Configuration(configDir.resolve(cfg.name()).toFile());
73+
val cat = rawConfig.getCategory(category);
74+
75+
for (val field: configClass.getDeclaredFields()) {
76+
if (field.getAnnotation(Config.Ignore.class) != null) continue;
77+
field.setAccessible(true);
78+
val comment = Optional.of(field.getAnnotation(Config.Comment.class)).map(Config.Comment::value).map((lines) -> String.join("\n", lines)).orElse("");
79+
val name = Optional.of(field.getAnnotation(Config.Name.class)).map(Config.Name::value).orElse(field.getName());
80+
val langKey = Optional.of(field.getAnnotation(Config.LangKey.class)).map(Config.LangKey::value).orElse(name);
81+
var boxed = false;
82+
Property prop = cat.get(name);
83+
prop.comment = comment;
84+
prop.setLanguageKey(langKey);
85+
if ((boxed = field.getType().equals(Integer.class)) || field.getType().equals(int.class)) {
86+
val range = Optional.of(field.getAnnotation(Config.RangeInt.class));
87+
prop.setMinValue(range.map(Config.RangeInt::min).orElse(Integer.MIN_VALUE));
88+
prop.setMaxValue(range.map(Config.RangeInt::max).orElse(Integer.MAX_VALUE));
89+
prop.setDefaultValue(Optional.of(field.getAnnotation(Config.DefaultInt.class)).map(Config.DefaultInt::value).orElse(boxed ? (Integer)field.get(null) : field.getInt(null)));
90+
field.setInt(null, prop.getInt());
91+
} else if ((boxed = field.getType().equals(Double.class)) || field.getType().equals(double.class)) {
92+
val range = Optional.of(field.getAnnotation(Config.RangeDouble.class));
93+
prop.setMinValue(range.map(Config.RangeDouble::min).orElse(Double.MIN_VALUE));
94+
prop.setMaxValue(range.map(Config.RangeDouble::max).orElse(Double.MAX_VALUE));
95+
prop.setDefaultValue(Optional.of(field.getAnnotation(Config.DefaultDouble.class)).map(Config.DefaultDouble::value).orElse(boxed ? (Double) field.get(null) : field.getDouble(null)));
96+
field.setDouble(null, prop.getDouble());
97+
} else if ((boxed = field.getType().equals(Boolean.class)) || field.getType().equals(boolean.class)) {
98+
prop.setDefaultValue(boxed ? (Boolean)field.get(null) : field.getBoolean(null));
99+
field.setBoolean(null, prop.getBoolean());
100+
} else if (field.getType().equals(String.class)) {
101+
prop.setDefaultValue((String)field.get(null));
102+
field.set(null, prop.getString());
103+
}
104+
if (field.isAnnotationPresent(Config.RequiresMcRestart.class)) {
105+
cat.setRequiresMcRestart(true);
106+
}
107+
if (field.isAnnotationPresent(Config.RequiresWorldRestart.class)) {
108+
cat.setRequiresWorldRestart(true);
109+
}
110+
}
111+
}
112+
}

src/main/java/com/falsepattern/lib/internal/FalsePatternLib.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
package com.falsepattern.lib.internal;
22

3+
import com.falsepattern.lib.config.ConfigurationManager;
34
import com.falsepattern.lib.util.ResourceUtil;
45
import com.google.common.eventbus.EventBus;
56
import cpw.mods.fml.common.DummyModContainer;
67
import cpw.mods.fml.common.LoadController;
78
import cpw.mods.fml.common.MetadataCollection;
8-
import cpw.mods.fml.common.ModMetadata;
99
import lombok.Getter;
10-
import lombok.val;
1110
import net.minecraft.launchwrapper.Launch;
1211
import org.apache.logging.log4j.LogManager;
1312
import org.apache.logging.log4j.Logger;
1413

15-
import java.util.Arrays;
16-
1714
/**
1815
* Utility class used by FalsePatternLib's internal code. This can change between versions without notice, so do not use this in your code!
1916
*/
@@ -26,6 +23,7 @@ public class FalsePatternLib extends DummyModContainer {
2623

2724
public FalsePatternLib() {
2825
super(MetadataCollection.from(ResourceUtil.getResourceFromJar("/mcmod.info", FalsePatternLib.class), Tags.MODID).getMetadataForId(Tags.MODID, null));
26+
ConfigurationManager.init();
2927
log.info("Version " + Tags.VERSION + " initialized!");
3028
}
3129

0 commit comments

Comments
 (0)