175 lines
6.1 KiB
Java
175 lines
6.1 KiB
Java
package io.gitlab.jfronny.libjf.config.impl;
|
|
|
|
import io.gitlab.jfronny.libjf.LibJf;
|
|
import io.gitlab.jfronny.libjf.config.api.ConfigInstance;
|
|
import io.gitlab.jfronny.libjf.config.api.Entry;
|
|
import io.gitlab.jfronny.libjf.config.api.Preset;
|
|
import io.gitlab.jfronny.libjf.config.api.Verifier;
|
|
import net.fabricmc.loader.api.FabricLoader;
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.Method;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.*;
|
|
|
|
/** Based on https://github.com/TeamMidnightDust/MidnightLib which is based on https://github.com/Minenash/TinyConfig
|
|
* Credits to TeamMidnightDust and Minenash */
|
|
|
|
public class ConfigInstanceImpl implements ConfigInstance {
|
|
public final List<EntryInfo> entries = new ArrayList<>();
|
|
public final Map<String, Runnable> presets = new LinkedHashMap<>();
|
|
public final Set<Runnable> verifiers = new LinkedHashSet<>();
|
|
public final Path path;
|
|
public final String modid;
|
|
public final Class<?> configClass;
|
|
|
|
public ConfigInstanceImpl(String modid, Class<?> config) {
|
|
this.modid = modid;
|
|
configClass = config;
|
|
path = FabricLoader.getInstance().getConfigDir().resolve(modid + ".json");
|
|
|
|
for (Field field : config.getFields()) {
|
|
EntryInfo info = new EntryInfo();
|
|
info.field = field;
|
|
if (field.isAnnotationPresent(Entry.class)) {
|
|
info.entry = field.getAnnotation(Entry.class);
|
|
try {
|
|
info.defaultValue = field.get(null);
|
|
} catch (IllegalAccessException ignored) {}
|
|
}
|
|
entries.add(info);
|
|
}
|
|
presets.put("libjf-config-v0.default", () -> {
|
|
for (EntryInfo entry : entries) {
|
|
try {
|
|
entry.field.set(null, entry.defaultValue);
|
|
} catch (IllegalAccessException e) {
|
|
LibJf.LOGGER.error("Could not reload default values", e);
|
|
}
|
|
}
|
|
});
|
|
for (Method method : config.getMethods()) {
|
|
if (method.isAnnotationPresent(Preset.class)) {
|
|
presets.put(modid + ".jfconfig." + method.getName(), () -> {
|
|
try {
|
|
method.invoke(null);
|
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
LibJf.LOGGER.error("Could not apply preset", e);
|
|
}
|
|
});
|
|
}
|
|
else if (method.isAnnotationPresent(Verifier.class)) {
|
|
verifiers.add(() -> {
|
|
try {
|
|
method.invoke(null);
|
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
LibJf.LOGGER.error("Could not run verifier", e);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
verifiers.add(() -> {
|
|
for (EntryInfo entry : entries) {
|
|
Object value;
|
|
try {
|
|
value = entry.field.get(null);
|
|
} catch (IllegalAccessException e) {
|
|
LibJf.LOGGER.error("Could not read value", e);
|
|
continue;
|
|
}
|
|
final Object valueOriginal = value;
|
|
if (value instanceof final Integer v) {
|
|
if (v < entry.entry.min()) value = (int)entry.entry.min();
|
|
if (v > entry.entry.max()) value = (int)entry.entry.max();
|
|
} else if (value instanceof final Float v) {
|
|
if (v < entry.entry.min()) value = (float)entry.entry.min();
|
|
if (v > entry.entry.max()) value = (float)entry.entry.max();
|
|
} else if (value instanceof final Double v) {
|
|
if (v < entry.entry.min()) value = entry.entry.min();
|
|
if (v > entry.entry.max()) value = entry.entry.max();
|
|
}
|
|
if (valueOriginal != value) {
|
|
try {
|
|
entry.field.set(null, value);
|
|
} catch (IllegalAccessException e) {
|
|
LibJf.LOGGER.error("Could not write value", e);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
load();
|
|
}
|
|
|
|
@Override
|
|
public void load() {
|
|
try {
|
|
LibJf.GSON.fromJson(Files.newBufferedReader(path), configClass);
|
|
}
|
|
catch (Exception e) {
|
|
LibJf.LOGGER.error("Could not read config", e);
|
|
}
|
|
syncFromClass();
|
|
write();
|
|
}
|
|
|
|
@Override
|
|
public void syncToClass() {
|
|
for (EntryInfo info : entries) {
|
|
try {
|
|
info.field.set(null, info.value);
|
|
} catch (IllegalAccessException e) {
|
|
LibJf.LOGGER.error("Could not write value", e);
|
|
}
|
|
}
|
|
syncFromClass();
|
|
}
|
|
|
|
@Override
|
|
public void syncFromClass() {
|
|
for (Runnable verifier : verifiers) {
|
|
verifier.run();
|
|
}
|
|
for (EntryInfo info : entries) {
|
|
try {
|
|
info.value = info.field.get(null);
|
|
if (info.value == null) info.value = info.defaultValue;
|
|
info.tempValue = info.value == null ? null : info.value.toString();
|
|
} catch (IllegalAccessException e) {
|
|
LibJf.LOGGER.error("Could not read value", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void write() {
|
|
try {
|
|
if (!Files.exists(path)) Files.createFile(path);
|
|
Files.write(path, LibJf.GSON.toJson(configClass.getDeclaredConstructor().newInstance()).getBytes());
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String getModId() {
|
|
return modid;
|
|
}
|
|
|
|
@Override
|
|
public boolean matchesConfigClass(Class<?> candidate) {
|
|
return candidate != null && candidate.isAssignableFrom(configClass);
|
|
}
|
|
|
|
@Override
|
|
public List<EntryInfo> getEntries() {
|
|
return entries;
|
|
}
|
|
|
|
@Override
|
|
public Map<String, Runnable> getPresets() {
|
|
return presets;
|
|
}
|
|
}
|