Skip to content

Commit

Permalink
auto remove dead config categories/values from file (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lyfts authored Oct 21, 2024
1 parent e12a874 commit 4ddb3e8
Showing 1 changed file with 46 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,21 @@ public class ConfigurationManager {
private static final Boolean PRINT_KEYS = Boolean.getBoolean("gtnhlib.printkeys");
private static final Boolean DUMP_KEYS = Boolean.getBoolean("gtnhlib.dumpkeys");
private static final Map<String, List<String>> generatedLangKeys = new HashMap<>();
private static final Map<Configuration, Set<String>> observedCategories = new HashMap<>();

private static final ConfigurationManager instance = new ConfigurationManager();
private final static Path configDir;

private static boolean initialized = false;

private static Path configDir;
static {
configDir = minecraftHome().toPath().resolve("config");
}

/**
* Registers a configuration class to be loaded. This should be done before or during preInit.
*
* @param configClass The class to register.
*/
public static void registerConfig(Class<?> configClass) throws ConfigException {
init();
val cfg = Optional.ofNullable(configClass.getAnnotation(Config.class)).orElseThrow(
() -> new ConfigException("Class " + configClass.getName() + " does not have a @Config annotation!"));
val category = cfg.category().trim().toLowerCase();
Expand Down Expand Up @@ -171,6 +172,7 @@ private static void processConfigInternal(Class<?> configClass, String category,
boolean requiresWorldRestart = getClassOrBaseAnnotation(configClass, Config.RequiresWorldRestart.class) != null
|| foundCategory && cat.requiresWorldRestart();

List<String> observedValues = new ArrayList<>();
for (val field : configClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Config.Ignore.class)) {
continue;
Expand Down Expand Up @@ -204,12 +206,10 @@ private static void processConfigInternal(Class<?> configClass, String category,

if (category.isEmpty()) continue;

val langKey = getLangKey(
configClass,
field.getAnnotation(Config.LangKey.class),
ConfigFieldParser.getFieldName(field),
cat);
val fieldName = ConfigFieldParser.getFieldName(field);
val langKey = getLangKey(configClass, field.getAnnotation(Config.LangKey.class), fieldName, cat);
ConfigFieldParser.loadField(instance, field, rawConfig, category, langKey);
observedValues.add(fieldName);

if (!requiresMcRestart) {
requiresMcRestart = field.isAnnotationPresent(Config.RequiresMcRestart.class);
Expand All @@ -225,12 +225,20 @@ private static void processConfigInternal(Class<?> configClass, String category,
}

if (category.isEmpty()) return;

if (cat.keySet().size() != observedValues.size()) {
val properties = new ArrayList<>(cat.keySet());
properties.removeIf(observedValues::contains);
properties.forEach(cat::remove);
}

if (cat.getLanguagekey().equals(category)) {
val langKey = getLangKey(configClass, configClass.getAnnotation(Config.LangKey.class), null, cat);
cat.setLanguageKey(langKey);
}
cat.setRequiresMcRestart(requiresMcRestart);
cat.setRequiresWorldRestart(requiresWorldRestart);
observedCategories.computeIfAbsent(rawConfig, k -> new HashSet<>()).add(cat.getQualifiedName());

Optional.ofNullable(configClass.getAnnotation(Config.Comment.class)).map(Config.Comment::value)
.map((lines) -> String.join("\n", lines)).ifPresent(cat::setComment);
Expand Down Expand Up @@ -258,7 +266,6 @@ public static List<IConfigElement> getConfigElements(Class<?> configClass) throw
@SuppressWarnings("rawtypes")
public static List<IConfigElement> getConfigElements(Class<?> configClass, boolean categorized)
throws ConfigException {
init();
val cfg = Optional.ofNullable(configClass.getAnnotation(Config.class)).orElseThrow(
() -> new ConfigException("Class " + configClass.getName() + " does not have a @Config annotation!"));
val rawConfig = Optional.ofNullable(configs.get(getConfigKey(cfg))).map(
Expand Down Expand Up @@ -440,15 +447,8 @@ private static File minecraftHome() {
return Launch.minecraftHome != null ? Launch.minecraftHome : new File(".");
}

private static void init() {
if (initialized) {
return;
}
configDir = minecraftHome().toPath().resolve("config");
initialized = true;
}

public static void onInit() {
cullDeadCategories();
if (DUMP_KEYS) {
writeLangKeysToFile();
}
Expand All @@ -468,4 +468,32 @@ private static void writeLangKeysToFile() {
}
}
}

private static void cullDeadCategories() {
for (val entry : observedCategories.entrySet()) {
val config = entry.getKey();
val observedCategoryNames = entry.getValue();

if (config.getCategoryNames().size() == observedCategoryNames.size()) {
continue;
}

val savedCategoryNames = new ArrayList<>(config.getCategoryNames());
savedCategoryNames.removeIf(observedCategoryNames::contains);

// Only keep the top-level category that needs removal otherwise getCategory() for any subcategory will
// recreate it.
List<String> parentsToRemove = savedCategoryNames.stream()
.filter(s -> savedCategoryNames.stream().noneMatch(existing -> s.startsWith(existing + ".")))
.collect(Collectors.toList());

for (val category : parentsToRemove) {
ConfigCategory cat = config.getCategory(category);
config.removeCategory(cat);
}

config.save();
}
observedCategories.clear();
}
}

0 comments on commit 4ddb3e8

Please sign in to comment.